]> git.sesse.net Git - ffmpeg/blob - libavfilter/af_adenorm.c
avformat/rtsp: check return value of ffurl_read_complete
[ffmpeg] / libavfilter / af_adenorm.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include "libavutil/avassert.h"
20 #include "libavutil/channel_layout.h"
21 #include "libavutil/opt.h"
22 #include "audio.h"
23 #include "avfilter.h"
24 #include "internal.h"
25
26 enum FilterType {
27     DC_TYPE,
28     AC_TYPE,
29     SQ_TYPE,
30     PS_TYPE,
31     NB_TYPES,
32 };
33
34 typedef struct ADenormContext {
35     const AVClass *class;
36
37     double level;
38     double level_db;
39     int type;
40     int64_t in_samples;
41
42     void (*filter)(AVFilterContext *ctx, void *dst,
43                    const void *src, int nb_samples);
44 } ADenormContext;
45
46 static int query_formats(AVFilterContext *ctx)
47 {
48     AVFilterFormats *formats = NULL;
49     AVFilterChannelLayouts *layouts = NULL;
50     static const enum AVSampleFormat sample_fmts[] = {
51         AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
52         AV_SAMPLE_FMT_NONE
53     };
54     int ret;
55
56     formats = ff_make_format_list(sample_fmts);
57     if (!formats)
58         return AVERROR(ENOMEM);
59     ret = ff_set_common_formats(ctx, formats);
60     if (ret < 0)
61         return ret;
62
63     layouts = ff_all_channel_counts();
64     if (!layouts)
65         return AVERROR(ENOMEM);
66
67     ret = ff_set_common_channel_layouts(ctx, layouts);
68     if (ret < 0)
69         return ret;
70
71     formats = ff_all_samplerates();
72     return ff_set_common_samplerates(ctx, formats);
73 }
74
75 static void dc_denorm_fltp(AVFilterContext *ctx, void *dstp,
76                            const void *srcp, int nb_samples)
77 {
78     ADenormContext *s = ctx->priv;
79     const float *src = (const float *)srcp;
80     float *dst = (float *)dstp;
81     const float dc = s->level;
82
83     for (int n = 0; n < nb_samples; n++) {
84         dst[n] = src[n] + dc;
85     }
86 }
87
88 static void dc_denorm_dblp(AVFilterContext *ctx, void *dstp,
89                            const void *srcp, int nb_samples)
90 {
91     ADenormContext *s = ctx->priv;
92     const double *src = (const double *)srcp;
93     double *dst = (double *)dstp;
94     const double dc = s->level;
95
96     for (int n = 0; n < nb_samples; n++) {
97         dst[n] = src[n] + dc;
98     }
99 }
100
101 static void ac_denorm_fltp(AVFilterContext *ctx, void *dstp,
102                            const void *srcp, int nb_samples)
103 {
104     ADenormContext *s = ctx->priv;
105     const float *src = (const float *)srcp;
106     float *dst = (float *)dstp;
107     const float dc = s->level;
108     const int64_t N = s->in_samples;
109
110     for (int n = 0; n < nb_samples; n++) {
111         dst[n] = src[n] + dc * (((N + n) & 1) ? -1.f : 1.f);
112     }
113 }
114
115 static void ac_denorm_dblp(AVFilterContext *ctx, void *dstp,
116                            const void *srcp, int nb_samples)
117 {
118     ADenormContext *s = ctx->priv;
119     const double *src = (const double *)srcp;
120     double *dst = (double *)dstp;
121     const double dc = s->level;
122     const int64_t N = s->in_samples;
123
124     for (int n = 0; n < nb_samples; n++) {
125         dst[n] = src[n] + dc * (((N + n) & 1) ? -1. : 1.);
126     }
127 }
128
129 static void sq_denorm_fltp(AVFilterContext *ctx, void *dstp,
130                            const void *srcp, int nb_samples)
131 {
132     ADenormContext *s = ctx->priv;
133     const float *src = (const float *)srcp;
134     float *dst = (float *)dstp;
135     const float dc = s->level;
136     const int64_t N = s->in_samples;
137
138     for (int n = 0; n < nb_samples; n++) {
139         dst[n] = src[n] + dc * ((((N + n) >> 8) & 1) ? -1.f : 1.f);
140     }
141 }
142
143 static void sq_denorm_dblp(AVFilterContext *ctx, void *dstp,
144                            const void *srcp, int nb_samples)
145 {
146     ADenormContext *s = ctx->priv;
147     const double *src = (const double *)srcp;
148     double *dst = (double *)dstp;
149     const double dc = s->level;
150     const int64_t N = s->in_samples;
151
152     for (int n = 0; n < nb_samples; n++) {
153         dst[n] = src[n] + dc * ((((N + n) >> 8) & 1) ? -1. : 1.);
154     }
155 }
156
157 static void ps_denorm_fltp(AVFilterContext *ctx, void *dstp,
158                            const void *srcp, int nb_samples)
159 {
160     ADenormContext *s = ctx->priv;
161     const float *src = (const float *)srcp;
162     float *dst = (float *)dstp;
163     const float dc = s->level;
164     const int64_t N = s->in_samples;
165
166     for (int n = 0; n < nb_samples; n++) {
167         dst[n] = src[n] + dc * (((N + n) & 255) ? 0.f : 1.f);
168     }
169 }
170
171 static void ps_denorm_dblp(AVFilterContext *ctx, void *dstp,
172                            const void *srcp, int nb_samples)
173 {
174     ADenormContext *s = ctx->priv;
175     const double *src = (const double *)srcp;
176     double *dst = (double *)dstp;
177     const double dc = s->level;
178     const int64_t N = s->in_samples;
179
180     for (int n = 0; n < nb_samples; n++) {
181         dst[n] = src[n] + dc * (((N + n) & 255) ? 0. : 1.);
182     }
183 }
184
185 static int config_output(AVFilterLink *outlink)
186 {
187     AVFilterContext *ctx = outlink->src;
188     ADenormContext *s = ctx->priv;
189
190     switch (s->type) {
191     case DC_TYPE:
192         switch (outlink->format) {
193         case AV_SAMPLE_FMT_FLTP: s->filter = dc_denorm_fltp; break;
194         case AV_SAMPLE_FMT_DBLP: s->filter = dc_denorm_dblp; break;
195         }
196         break;
197     case AC_TYPE:
198         switch (outlink->format) {
199         case AV_SAMPLE_FMT_FLTP: s->filter = ac_denorm_fltp; break;
200         case AV_SAMPLE_FMT_DBLP: s->filter = ac_denorm_dblp; break;
201         }
202         break;
203     case SQ_TYPE:
204         switch (outlink->format) {
205         case AV_SAMPLE_FMT_FLTP: s->filter = sq_denorm_fltp; break;
206         case AV_SAMPLE_FMT_DBLP: s->filter = sq_denorm_dblp; break;
207         }
208         break;
209     case PS_TYPE:
210         switch (outlink->format) {
211         case AV_SAMPLE_FMT_FLTP: s->filter = ps_denorm_fltp; break;
212         case AV_SAMPLE_FMT_DBLP: s->filter = ps_denorm_dblp; break;
213         }
214         break;
215     default:
216         av_assert0(0);
217     }
218
219     return 0;
220 }
221
222 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
223 {
224     AVFilterContext *ctx = inlink->dst;
225     ADenormContext *s = ctx->priv;
226     AVFilterLink *outlink = ctx->outputs[0];
227     AVFrame *out;
228
229     if (av_frame_is_writable(in)) {
230         out = in;
231     } else {
232         out = ff_get_audio_buffer(outlink, in->nb_samples);
233         if (!out) {
234             av_frame_free(&in);
235             return AVERROR(ENOMEM);
236         }
237         av_frame_copy_props(out, in);
238     }
239
240     s->level = exp(s->level_db / 20. * M_LN10);
241     for (int ch = 0; ch < inlink->channels; ch++) {
242         s->filter(ctx, out->extended_data[ch],
243                   in->extended_data[ch],
244                   in->nb_samples);
245     }
246     s->in_samples += in->nb_samples;
247
248     if (out != in)
249         av_frame_free(&in);
250     return ff_filter_frame(outlink, out);
251 }
252
253 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
254                            char *res, int res_len, int flags)
255 {
256     AVFilterLink *outlink = ctx->outputs[0];
257     int ret;
258
259     ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
260     if (ret < 0)
261         return ret;
262
263     return config_output(outlink);
264 }
265
266 static const AVFilterPad adenorm_inputs[] = {
267     {
268         .name         = "default",
269         .type         = AVMEDIA_TYPE_AUDIO,
270         .filter_frame = filter_frame,
271     },
272     { NULL }
273 };
274
275 static const AVFilterPad adenorm_outputs[] = {
276     {
277         .name         = "default",
278         .type         = AVMEDIA_TYPE_AUDIO,
279         .config_props = config_output,
280     },
281     { NULL }
282 };
283
284 #define OFFSET(x) offsetof(ADenormContext, x)
285 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
286
287 static const AVOption adenorm_options[] = {
288     { "level", "set level", OFFSET(level_db), AV_OPT_TYPE_DOUBLE, {.dbl=-351},   -451,        -90, FLAGS },
289     { "type",  "set type",  OFFSET(type),     AV_OPT_TYPE_INT,    {.i64=DC_TYPE},   0, NB_TYPES-1, FLAGS, "type" },
290     { "dc",    NULL,  0, AV_OPT_TYPE_CONST, {.i64=DC_TYPE}, 0, 0, FLAGS, "type"},
291     { "ac",    NULL,  0, AV_OPT_TYPE_CONST, {.i64=AC_TYPE}, 0, 0, FLAGS, "type"},
292     { "square",NULL,  0, AV_OPT_TYPE_CONST, {.i64=SQ_TYPE}, 0, 0, FLAGS, "type"},
293     { "pulse", NULL,  0, AV_OPT_TYPE_CONST, {.i64=PS_TYPE}, 0, 0, FLAGS, "type"},
294     { NULL }
295 };
296
297 AVFILTER_DEFINE_CLASS(adenorm);
298
299 AVFilter ff_af_adenorm = {
300     .name            = "adenorm",
301     .description     = NULL_IF_CONFIG_SMALL("Remedy denormals by adding extremely low-level noise."),
302     .query_formats   = query_formats,
303     .priv_size       = sizeof(ADenormContext),
304     .inputs          = adenorm_inputs,
305     .outputs         = adenorm_outputs,
306     .priv_class      = &adenorm_class,
307     .process_command = process_command,
308 };