1 /*
2 * Copyright (c) 2016 The FFmpeg Project
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
26
34
35 #define OFFSET(x) offsetof(CrystalizerContext, x)
36 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
37
42 };
43
45
54
55 #define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed) \
56 static int filter_## inverse ##_## fmt ##_## clp(AVFilterContext *ctx, \
57 void *arg, int jobnr,\
58 int nb_jobs) \
59 { \
60 ThreadData *td = arg; \
61 void **d = td->d; \
62 void **p = td->p; \
63 const void **s = td->s; \
64 const int nb_samples = td->nb_samples; \
65 const int channels = td->channels; \
66 const type mult = td->mult; \
67 const type scale = one / (-mult + one); \
68 const int start = (channels * jobnr) / nb_jobs; \
69 const int end = (channels * (jobnr+1)) / nb_jobs; \
70 \
71 if (packed) { \
72 type *prv = p[0]; \
73 for (int c = start; c < end; c++) { \
74 const type *src = s[0]; \
75 type *dst = d[0]; \
76 \
77 for (int n = 0; n < nb_samples; n++) { \
78 type current = src[c]; \
79 \
80 if (inverset) { \
81 dst[c] = (current - prv[c] * mult) * scale; \
82 prv[c] = dst[c]; \
83 } else { \
84 dst[c] = current + (current - prv[c]) * mult; \
85 prv[c] = current; \
86 } \
87 if (clip) { \
88 dst[c] = clip_fn(dst[c], -one, one); \
89 } \
90 \
91 dst += channels; \
92 src += channels; \
93 } \
94 } \
95 } else { \
96 for (int c = start; c < end; c++) { \
97 const type *src = s[c]; \
98 type *dst = d[c]; \
99 type *prv = p[c]; \
100 \
101 for (int n = 0; n < nb_samples; n++) { \
102 type current = src[n]; \
103 \
104 if (inverset) { \
105 dst[n] = (current - prv[0] * mult) * scale; \
106 prv[0] = dst[n]; \
107 } else { \
108 dst[n] = current + (current - prv[0]) * mult; \
109 prv[0] = current; \
110 } \
111 if (clip) { \
112 dst[n] = clip_fn(dst[n], -one, one); \
113 } \
114 } \
115 } \
116 } \
117 \
118 return 0; \
119 }
120
125
130
135
140
142 {
145
148 s->filter[0][0] = filter_inverse_flt_noclip;
149 s->filter[1][0] = filter_noinverse_flt_noclip;
150 s->filter[0][1] = filter_inverse_flt_clip;
151 s->filter[1][1] = filter_noinverse_flt_clip;
152 break;
154 s->filter[0][0] = filter_inverse_fltp_noclip;
155 s->filter[1][0] = filter_noinverse_fltp_noclip;
156 s->filter[0][1] = filter_inverse_fltp_clip;
157 s->filter[1][1] = filter_noinverse_fltp_clip;
158 break;
160 s->filter[0][0] = filter_inverse_dbl_noclip;
161 s->filter[1][0] = filter_noinverse_dbl_noclip;
162 s->filter[0][1] = filter_inverse_dbl_clip;
163 s->filter[1][1] = filter_noinverse_dbl_clip;
164 break;
166 s->filter[0][0] = filter_inverse_dblp_noclip;
167 s->filter[1][0] = filter_noinverse_dblp_noclip;
168 s->filter[0][1] = filter_inverse_dblp_clip;
169 s->filter[1][1] = filter_noinverse_dblp_clip;
170 break;
171 default:
173 }
174
175 return 0;
176 }
177
179 {
185
191 }
192 }
193
196 } else {
201 }
203 }
204
205 td.
d = (
void **)
out->extended_data;
207 td.
p = (
void **)
s->prev->extended_data;
210 td.
mult =
ctx->is_disabled ? 0.f :
s->mult;
213
216
218 }
219
221 {
223
225 }
226
228 {
233 },
234 };
235
237 .
p.
name =
"crystalizer",
239 .p.priv_class = &crystalizer_class,
249 };