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
25
33
34 #define OFFSET(x) offsetof(CrystalizerContext, x)
35 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
36
41 };
42
44
53
54 #define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed) \
55 static int filter_## inverse ##_## fmt ##_## clp(AVFilterContext *ctx, \
56 void *arg, int jobnr,\
57 int nb_jobs) \
58 { \
59 ThreadData *td = arg; \
60 void **d = td->d; \
61 void **p = td->p; \
62 const void **s = td->s; \
63 const int nb_samples = td->nb_samples; \
64 const int channels = td->channels; \
65 const type mult = td->mult; \
66 const type scale = one / (-mult + one); \
67 const int start = (channels * jobnr) / nb_jobs; \
68 const int end = (channels * (jobnr+1)) / nb_jobs; \
69 \
70 if (packed) { \
71 type *prv = p[0]; \
72 for (int c = start; c < end; c++) { \
73 const type *src = s[0]; \
74 type *dst = d[0]; \
75 \
76 for (int n = 0; n < nb_samples; n++) { \
77 type current = src[c]; \
78 \
79 if (inverset) { \
80 dst[c] = (current - prv[c] * mult) * scale; \
81 prv[c] = dst[c]; \
82 } else { \
83 dst[c] = current + (current - prv[c]) * mult; \
84 prv[c] = current; \
85 } \
86 if (clip) { \
87 dst[c] = clip_fn(dst[c], -one, one); \
88 } \
89 \
90 dst += channels; \
91 src += channels; \
92 } \
93 } \
94 } else { \
95 for (int c = start; c < end; c++) { \
96 const type *src = s[c]; \
97 type *dst = d[c]; \
98 type *prv = p[c]; \
99 \
100 for (int n = 0; n < nb_samples; n++) { \
101 type current = src[n]; \
102 \
103 if (inverset) { \
104 dst[n] = (current - prv[0] * mult) * scale; \
105 prv[0] = dst[n]; \
106 } else { \
107 dst[n] = current + (current - prv[0]) * mult; \
108 prv[0] = current; \
109 } \
110 if (clip) { \
111 dst[n] = clip_fn(dst[n], -one, one); \
112 } \
113 } \
114 } \
115 } \
116 \
117 return 0; \
118 }
119
124
129
134
139
141 {
144
147 s->filter[0][0] = filter_inverse_flt_noclip;
148 s->filter[1][0] = filter_noinverse_flt_noclip;
149 s->filter[0][1] = filter_inverse_flt_clip;
150 s->filter[1][1] = filter_noinverse_flt_clip;
151 break;
153 s->filter[0][0] = filter_inverse_fltp_noclip;
154 s->filter[1][0] = filter_noinverse_fltp_noclip;
155 s->filter[0][1] = filter_inverse_fltp_clip;
156 s->filter[1][1] = filter_noinverse_fltp_clip;
157 break;
159 s->filter[0][0] = filter_inverse_dbl_noclip;
160 s->filter[1][0] = filter_noinverse_dbl_noclip;
161 s->filter[0][1] = filter_inverse_dbl_clip;
162 s->filter[1][1] = filter_noinverse_dbl_clip;
163 break;
165 s->filter[0][0] = filter_inverse_dblp_noclip;
166 s->filter[1][0] = filter_noinverse_dblp_noclip;
167 s->filter[0][1] = filter_inverse_dblp_clip;
168 s->filter[1][1] = filter_noinverse_dblp_clip;
169 break;
170 default:
172 }
173
174 return 0;
175 }
176
178 {
184
190 }
191 }
192
195 } else {
200 }
202 }
203
204 td.d = (
void **)
out->extended_data;
206 td.p = (
void **)
s->prev->extended_data;
209 td.mult =
ctx->is_disabled ? 0.f :
s->mult;
212
215
217 }
218
220 {
222
224 }
225
227 {
232 },
233 };
234
236 .
name =
"crystalizer",
239 .priv_class = &crystalizer_class,
248 };