1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/*
* 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/attributes.h"
#include "libavutil/cpu.h"
#include "libavutil/avassert.h"
#include "libavutil/arm/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_arm_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;
}
}
|