121 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Audio resampling | ||
|  |  * | ||
|  |  * Copyright (c) 2004-2012 Michael Niedermayer <michaelni@gmx.at> | ||
|  |  * | ||
|  |  * This file is part of FFmpeg. | ||
|  |  * | ||
|  |  * FFmpeg is free software; you can redistribute it and/or | ||
|  |  * modify it under the terms of the GNU Lesser General Public | ||
|  |  * License as published by the Free Software Foundation; either | ||
|  |  * version 2.1 of the License, or (at your option) any later version. | ||
|  |  * | ||
|  |  * FFmpeg is distributed in the hope that it will be useful, | ||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||
|  |  * Lesser General Public License for more details. | ||
|  |  * | ||
|  |  * You should have received a copy of the GNU Lesser General Public | ||
|  |  * License along with FFmpeg; if not, write to the Free Software | ||
|  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "config.h"
 | ||
|  | 
 | ||
|  | #include "libavutil/cpu.h"
 | ||
|  | #include "libavutil/avassert.h"
 | ||
|  | 
 | ||
|  | #include "libavutil/aarch64/cpu.h"
 | ||
|  | #include "libswresample/resample.h"
 | ||
|  | 
 | ||
|  | #define DECLARE_RESAMPLE_COMMON_TEMPLATE(TYPE, DELEM, FELEM, FELEM2, OUT)                         \
 | ||
|  |                                                                                                   \ | ||
|  | void ff_resample_common_apply_filter_x4_##TYPE##_neon(FELEM2 *acc, const DELEM *src,              \ | ||
|  |                                                       const FELEM *filter, int length);           \ | ||
|  |                                                                                                   \ | ||
|  | void ff_resample_common_apply_filter_x8_##TYPE##_neon(FELEM2 *acc, const DELEM *src,              \ | ||
|  |                                                       const FELEM *filter, int length);           \ | ||
|  |                                                                                                   \ | ||
|  | static int ff_resample_common_##TYPE##_neon(ResampleContext *c, void *dest, const void *source,   \ | ||
|  |                                             int n, int update_ctx)                                \ | ||
|  | {                                                                                                 \ | ||
|  |     DELEM *dst = dest;                                                                            \ | ||
|  |     const DELEM *src = source;                                                                    \ | ||
|  |     int dst_index;                                                                                \ | ||
|  |     int index = c->index;                                                                         \ | ||
|  |     int frac = c->frac;                                                                           \ | ||
|  |     int sample_index = 0;                                                                         \ | ||
|  |     int x4_aligned_filter_length = c->filter_length & ~3;                                         \ | ||
|  |     int x8_aligned_filter_length = c->filter_length & ~7;                                         \ | ||
|  |                                                                                                   \ | ||
|  |     while (index >= c->phase_count) {                                                             \ | ||
|  |         sample_index++;                                                                           \ | ||
|  |         index -= c->phase_count;                                                                  \ | ||
|  |     }                                                                                             \ | ||
|  |                                                                                                   \ | ||
|  |     for (dst_index = 0; dst_index < n; dst_index++) {                                             \ | ||
|  |         FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;                     \ | ||
|  |                                                                                                   \ | ||
|  |         FELEM2 val = 0;                                                                             \ | ||
|  |         int i = 0;                                                                                \ | ||
|  |         if (x8_aligned_filter_length >= 8) {                                                      \ | ||
|  |             ff_resample_common_apply_filter_x8_##TYPE##_neon(&val, &src[sample_index],            \ | ||
|  |                                                              filter, x8_aligned_filter_length);   \ | ||
|  |             i += x8_aligned_filter_length;                                                        \ | ||
|  |                                                                                                   \ | ||
|  |         } else if (x4_aligned_filter_length >= 4) {                                               \ | ||
|  |             ff_resample_common_apply_filter_x4_##TYPE##_neon(&val, &src[sample_index],            \ | ||
|  |                                                              filter, x4_aligned_filter_length);   \ | ||
|  |             i += x4_aligned_filter_length;                                                        \ | ||
|  |         }                                                                                         \ | ||
|  |         for (; i < c->filter_length; i++) {                                                       \ | ||
|  |             val += src[sample_index + i] * (FELEM2)filter[i];                                     \ | ||
|  |         }                                                                                         \ | ||
|  |         OUT(dst[dst_index], val);                                                                 \ | ||
|  |                                                                                                   \ | ||
|  |         frac  += c->dst_incr_mod;                                                                 \ | ||
|  |         index += c->dst_incr_div;                                                                 \ | ||
|  |         if (frac >= c->src_incr) {                                                                \ | ||
|  |             frac -= c->src_incr;                                                                  \ | ||
|  |             index++;                                                                              \ | ||
|  |         }                                                                                         \ | ||
|  |                                                                                                   \ | ||
|  |         while (index >= c->phase_count) {                                                         \ | ||
|  |             sample_index++;                                                                       \ | ||
|  |             index -= c->phase_count;                                                              \ | ||
|  |         }                                                                                         \ | ||
|  |     }                                                                                             \ | ||
|  |                                                                                                   \ | ||
|  |     if (update_ctx) {                                                                             \ | ||
|  |         c->frac = frac;                                                                           \ | ||
|  |         c->index = index;                                                                         \ | ||
|  |     }                                                                                             \ | ||
|  |                                                                                                   \ | ||
|  |     return sample_index;                                                                          \ | ||
|  | }                                                                                                 \ | ||
|  | 
 | ||
|  | #define OUT(d, v) d = v
 | ||
|  | DECLARE_RESAMPLE_COMMON_TEMPLATE(float, float, float, float, OUT) | ||
|  | #undef OUT
 | ||
|  | 
 | ||
|  | #define OUT(d, v) (v) = ((v) + (1<<(14)))>>15; (d) = av_clip_int16(v)
 | ||
|  | DECLARE_RESAMPLE_COMMON_TEMPLATE(s16, int16_t, int16_t, int32_t, OUT) | ||
|  | #undef OUT
 | ||
|  | 
 | ||
|  | av_cold void swri_resample_dsp_aarch64_init(ResampleContext *c) | ||
|  | { | ||
|  |     int cpu_flags = av_get_cpu_flags(); | ||
|  | 
 | ||
|  |     if (!have_neon(cpu_flags)) | ||
|  |         return; | ||
|  | 
 | ||
|  |     switch(c->format) { | ||
|  |     case AV_SAMPLE_FMT_FLTP: | ||
|  |         c->dsp.resample_common = ff_resample_common_float_neon; | ||
|  |         break; | ||
|  |     case AV_SAMPLE_FMT_S16P: | ||
|  |         c->dsp.resample_common = ff_resample_common_s16_neon; | ||
|  |         break; | ||
|  |     } | ||
|  | } |