1f67014a1c64c4e95ee5300df46e56484510bf76
[ffmpeg.git] / libavfilter / af_astats.c
1 /*
2  * Copyright (c) 2009 Rob Sykes <robs@users.sourceforge.net>
3  * Copyright (c) 2013 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <float.h>
23
24 #include "libavutil/opt.h"
25 #include "audio.h"
26 #include "avfilter.h"
27 #include "internal.h"
28
29 typedef struct ChannelStats {
30     double last;
31     double sigma_x, sigma_x2;
32     double avg_sigma_x2, min_sigma_x2, max_sigma_x2;
33     double min, max;
34     double min_run, max_run;
35     double min_runs, max_runs;
36     uint64_t mask;
37     uint64_t min_count, max_count;
38     uint64_t nb_samples;
39 } ChannelStats;
40
41 typedef struct {
42     const AVClass *class;
43     ChannelStats *chstats;
44     int nb_channels;
45     uint64_t tc_samples;
46     double time_constant;
47     double mult;
48     int metadata;
49     int reset_count;
50     int nb_frames;
51 } AudioStatsContext;
52
53 #define OFFSET(x) offsetof(AudioStatsContext, x)
54 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
55
56 static const AVOption astats_options[] = {
57     { "length", "set the window length", OFFSET(time_constant), AV_OPT_TYPE_DOUBLE, {.dbl=.05}, .01, 10, FLAGS },
58     { "metadata", "inject metadata in the filtergraph", OFFSET(metadata), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS },
59     { "reset", "recalculate stats after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
60     { NULL }
61 };
62
63 AVFILTER_DEFINE_CLASS(astats);
64
65 static int query_formats(AVFilterContext *ctx)
66 {
67     AVFilterFormats *formats;
68     AVFilterChannelLayouts *layouts;
69     static const enum AVSampleFormat sample_fmts[] = {
70         AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
71         AV_SAMPLE_FMT_NONE
72     };
73     int ret;
74
75     layouts = ff_all_channel_layouts();
76     if (!layouts)
77         return AVERROR(ENOMEM);
78     ret = ff_set_common_channel_layouts(ctx, layouts);
79     if (ret < 0)
80         return ret;
81
82     formats = ff_make_format_list(sample_fmts);
83     if (!formats)
84         return AVERROR(ENOMEM);
85     ret = ff_set_common_formats(ctx, formats);
86     if (ret < 0)
87         return ret;
88
89     formats = ff_all_samplerates();
90     if (!formats)
91         return AVERROR(ENOMEM);
92     return ff_set_common_samplerates(ctx, formats);
93 }
94
95 static void reset_stats(AudioStatsContext *s)
96 {
97     int c;
98
99     memset(s->chstats, 0, sizeof(*s->chstats));
100
101     for (c = 0; c < s->nb_channels; c++) {
102         ChannelStats *p = &s->chstats[c];
103
104         p->min = p->min_sigma_x2 = DBL_MAX;
105         p->max = p->max_sigma_x2 = DBL_MIN;
106     }
107 }
108
109 static int config_output(AVFilterLink *outlink)
110 {
111     AudioStatsContext *s = outlink->src->priv;
112
113     s->chstats = av_calloc(sizeof(*s->chstats), outlink->channels);
114     if (!s->chstats)
115         return AVERROR(ENOMEM);
116     s->nb_channels = outlink->channels;
117     s->mult = exp((-1 / s->time_constant / outlink->sample_rate));
118     s->tc_samples = 5 * s->time_constant * outlink->sample_rate + .5;
119
120     reset_stats(s);
121
122     return 0;
123 }
124
125 static unsigned bit_depth(uint64_t mask)
126 {
127     unsigned result = 64;
128
129     for (; result && !(mask & 1); --result, mask >>= 1);
130
131     return result;
132 }
133
134 static inline void update_stat(AudioStatsContext *s, ChannelStats *p, double d)
135 {
136     if (d < p->min) {
137         p->min = d;
138         p->min_run = 1;
139         p->min_runs = 0;
140         p->min_count = 1;
141     } else if (d == p->min) {
142         p->min_count++;
143         p->min_run = d == p->last ? p->min_run + 1 : 1;
144     } else if (p->last == p->min) {
145         p->min_runs += p->min_run * p->min_run;
146     }
147
148     if (d > p->max) {
149         p->max = d;
150         p->max_run = 1;
151         p->max_runs = 0;
152         p->max_count = 1;
153     } else if (d == p->max) {
154         p->max_count++;
155         p->max_run = d == p->last ? p->max_run + 1 : 1;
156     } else if (p->last == p->max) {
157         p->max_runs += p->max_run * p->max_run;
158     }
159
160     p->sigma_x += d;
161     p->sigma_x2 += d * d;
162     p->avg_sigma_x2 = p->avg_sigma_x2 * s->mult + (1.0 - s->mult) * d * d;
163     p->last = d;
164     p->mask |= llrint(d * (1LLU<<63));
165
166     if (p->nb_samples >= s->tc_samples) {
167         p->max_sigma_x2 = FFMAX(p->max_sigma_x2, p->avg_sigma_x2);
168         p->min_sigma_x2 = FFMIN(p->min_sigma_x2, p->avg_sigma_x2);
169     }
170     p->nb_samples++;
171 }
172
173 static void set_meta(AVDictionary **metadata, int chan, const char *key,
174                      const char *fmt, double val)
175 {
176     uint8_t value[128];
177     uint8_t key2[128];
178
179     snprintf(value, sizeof(value), fmt, val);
180     if (chan)
181         snprintf(key2, sizeof(key2), "lavfi.astats.%d.%s", chan, key);
182     else
183         snprintf(key2, sizeof(key2), "lavfi.astats.%s", key);
184     av_dict_set(metadata, key2, value, 0);
185 }
186
187 #define LINEAR_TO_DB(x) (log10(x) * 20)
188
189 static void set_metadata(AudioStatsContext *s, AVDictionary **metadata)
190 {
191     uint64_t mask = 0, min_count = 0, max_count = 0, nb_samples = 0;
192     double min_runs = 0, max_runs = 0,
193            min = DBL_MAX, max = DBL_MIN,
194            max_sigma_x = 0,
195            sigma_x = 0,
196            sigma_x2 = 0,
197            min_sigma_x2 = DBL_MAX,
198            max_sigma_x2 = DBL_MIN;
199     int c;
200
201     for (c = 0; c < s->nb_channels; c++) {
202         ChannelStats *p = &s->chstats[c];
203
204         if (p->nb_samples < s->tc_samples)
205             p->min_sigma_x2 = p->max_sigma_x2 = p->sigma_x2 / p->nb_samples;
206
207         min = FFMIN(min, p->min);
208         max = FFMAX(max, p->max);
209         min_sigma_x2 = FFMIN(min_sigma_x2, p->min_sigma_x2);
210         max_sigma_x2 = FFMAX(max_sigma_x2, p->max_sigma_x2);
211         sigma_x += p->sigma_x;
212         sigma_x2 += p->sigma_x2;
213         min_count += p->min_count;
214         max_count += p->max_count;
215         min_runs += p->min_runs;
216         max_runs += p->max_runs;
217         mask |= p->mask;
218         nb_samples += p->nb_samples;
219         if (fabs(p->sigma_x) > fabs(max_sigma_x))
220             max_sigma_x = p->sigma_x;
221
222         set_meta(metadata, c + 1, "DC_offset", "%f", p->sigma_x / p->nb_samples);
223         set_meta(metadata, c + 1, "Min_level", "%f", p->min);
224         set_meta(metadata, c + 1, "Max_level", "%f", p->max);
225         set_meta(metadata, c + 1, "Peak_level", "%f", LINEAR_TO_DB(FFMAX(-p->min, p->max)));
226         set_meta(metadata, c + 1, "RMS_level", "%f", LINEAR_TO_DB(sqrt(p->sigma_x2 / p->nb_samples)));
227         set_meta(metadata, c + 1, "RMS_peak", "%f", LINEAR_TO_DB(sqrt(p->max_sigma_x2)));
228         set_meta(metadata, c + 1, "RMS_trough", "%f", LINEAR_TO_DB(sqrt(p->min_sigma_x2)));
229         set_meta(metadata, c + 1, "Crest_factor", "%f", p->sigma_x2 ? FFMAX(-p->min, p->max) / sqrt(p->sigma_x2 / p->nb_samples) : 1);
230         set_meta(metadata, c + 1, "Flat_factor", "%f", LINEAR_TO_DB((p->min_runs + p->max_runs) / (p->min_count + p->max_count)));
231         set_meta(metadata, c + 1, "Peak_count", "%f", (float)(p->min_count + p->max_count));
232         set_meta(metadata, c + 1, "Bit_depth", "%f", bit_depth(p->mask));
233     }
234
235     set_meta(metadata, 0, "Overall.DC_offset", "%f", max_sigma_x / (nb_samples / s->nb_channels));
236     set_meta(metadata, 0, "Overall.Min_level", "%f", min);
237     set_meta(metadata, 0, "Overall.Max_level", "%f", max);
238     set_meta(metadata, 0, "Overall.Peak_level", "%f", LINEAR_TO_DB(FFMAX(-min, max)));
239     set_meta(metadata, 0, "Overall.RMS_level", "%f", LINEAR_TO_DB(sqrt(sigma_x2 / nb_samples)));
240     set_meta(metadata, 0, "Overall.RMS_peak", "%f", LINEAR_TO_DB(sqrt(max_sigma_x2)));
241     set_meta(metadata, 0, "Overall.RMS_trough", "%f", LINEAR_TO_DB(sqrt(min_sigma_x2)));
242     set_meta(metadata, 0, "Overall.Flat_factor", "%f", LINEAR_TO_DB((min_runs + max_runs) / (min_count + max_count)));
243     set_meta(metadata, 0, "Overall.Peak_count", "%f", (float)(min_count + max_count) / (double)s->nb_channels);
244     set_meta(metadata, 0, "Overall.Bit_depth", "%f", bit_depth(mask));
245     set_meta(metadata, 0, "Overall.Number_of_samples", "%f", nb_samples / s->nb_channels);
246 }
247
248 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
249 {
250     AudioStatsContext *s = inlink->dst->priv;
251     AVDictionary **metadata = avpriv_frame_get_metadatap(buf);
252     const int channels = s->nb_channels;
253     const double *src;
254     int i, c;
255
256     switch (inlink->format) {
257     case AV_SAMPLE_FMT_DBLP:
258         for (c = 0; c < channels; c++) {
259             ChannelStats *p = &s->chstats[c];
260             src = (const double *)buf->extended_data[c];
261
262             for (i = 0; i < buf->nb_samples; i++, src++)
263                 update_stat(s, p, *src);
264         }
265         break;
266     case AV_SAMPLE_FMT_DBL:
267         src = (const double *)buf->extended_data[0];
268
269         for (i = 0; i < buf->nb_samples; i++) {
270             for (c = 0; c < channels; c++, src++)
271                 update_stat(s, &s->chstats[c], *src);
272         }
273         break;
274     }
275
276     if (s->metadata)
277         set_metadata(s, metadata);
278
279     if (s->reset_count > 0) {
280         s->nb_frames++;
281         if (s->nb_frames >= s->reset_count) {
282             reset_stats(s);
283             s->nb_frames = 0;
284         }
285     }
286
287     return ff_filter_frame(inlink->dst->outputs[0], buf);
288 }
289
290 static void print_stats(AVFilterContext *ctx)
291 {
292     AudioStatsContext *s = ctx->priv;
293     uint64_t mask = 0, min_count = 0, max_count = 0, nb_samples = 0;
294     double min_runs = 0, max_runs = 0,
295            min = DBL_MAX, max = DBL_MIN,
296            max_sigma_x = 0,
297            sigma_x = 0,
298            sigma_x2 = 0,
299            min_sigma_x2 = DBL_MAX,
300            max_sigma_x2 = DBL_MIN;
301     int c;
302
303     for (c = 0; c < s->nb_channels; c++) {
304         ChannelStats *p = &s->chstats[c];
305
306         if (p->nb_samples < s->tc_samples)
307             p->min_sigma_x2 = p->max_sigma_x2 = p->sigma_x2 / p->nb_samples;
308
309         min = FFMIN(min, p->min);
310         max = FFMAX(max, p->max);
311         min_sigma_x2 = FFMIN(min_sigma_x2, p->min_sigma_x2);
312         max_sigma_x2 = FFMAX(max_sigma_x2, p->max_sigma_x2);
313         sigma_x += p->sigma_x;
314         sigma_x2 += p->sigma_x2;
315         min_count += p->min_count;
316         max_count += p->max_count;
317         min_runs += p->min_runs;
318         max_runs += p->max_runs;
319         mask |= p->mask;
320         nb_samples += p->nb_samples;
321         if (fabs(p->sigma_x) > fabs(max_sigma_x))
322             max_sigma_x = p->sigma_x;
323
324         av_log(ctx, AV_LOG_INFO, "Channel: %d\n", c + 1);
325         av_log(ctx, AV_LOG_INFO, "DC offset: %f\n", p->sigma_x / p->nb_samples);
326         av_log(ctx, AV_LOG_INFO, "Min level: %f\n", p->min);
327         av_log(ctx, AV_LOG_INFO, "Max level: %f\n", p->max);
328         av_log(ctx, AV_LOG_INFO, "Peak level dB: %f\n", LINEAR_TO_DB(FFMAX(-p->min, p->max)));
329         av_log(ctx, AV_LOG_INFO, "RMS level dB: %f\n", LINEAR_TO_DB(sqrt(p->sigma_x2 / p->nb_samples)));
330         av_log(ctx, AV_LOG_INFO, "RMS peak dB: %f\n", LINEAR_TO_DB(sqrt(p->max_sigma_x2)));
331         if (p->min_sigma_x2 != 1)
332             av_log(ctx, AV_LOG_INFO, "RMS trough dB: %f\n",LINEAR_TO_DB(sqrt(p->min_sigma_x2)));
333         av_log(ctx, AV_LOG_INFO, "Crest factor: %f\n", p->sigma_x2 ? FFMAX(-p->min, p->max) / sqrt(p->sigma_x2 / p->nb_samples) : 1);
334         av_log(ctx, AV_LOG_INFO, "Flat factor: %f\n", LINEAR_TO_DB((p->min_runs + p->max_runs) / (p->min_count + p->max_count)));
335         av_log(ctx, AV_LOG_INFO, "Peak count: %"PRId64"\n", p->min_count + p->max_count);
336         av_log(ctx, AV_LOG_INFO, "Bit depth: %u\n", bit_depth(p->mask));
337     }
338
339     av_log(ctx, AV_LOG_INFO, "Overall\n");
340     av_log(ctx, AV_LOG_INFO, "DC offset: %f\n", max_sigma_x / (nb_samples / s->nb_channels));
341     av_log(ctx, AV_LOG_INFO, "Min level: %f\n", min);
342     av_log(ctx, AV_LOG_INFO, "Max level: %f\n", max);
343     av_log(ctx, AV_LOG_INFO, "Peak level dB: %f\n", LINEAR_TO_DB(FFMAX(-min, max)));
344     av_log(ctx, AV_LOG_INFO, "RMS level dB: %f\n", LINEAR_TO_DB(sqrt(sigma_x2 / nb_samples)));
345     av_log(ctx, AV_LOG_INFO, "RMS peak dB: %f\n", LINEAR_TO_DB(sqrt(max_sigma_x2)));
346     if (min_sigma_x2 != 1)
347         av_log(ctx, AV_LOG_INFO, "RMS trough dB: %f\n", LINEAR_TO_DB(sqrt(min_sigma_x2)));
348     av_log(ctx, AV_LOG_INFO, "Flat factor: %f\n", LINEAR_TO_DB((min_runs + max_runs) / (min_count + max_count)));
349     av_log(ctx, AV_LOG_INFO, "Peak count: %f\n", (min_count + max_count) / (double)s->nb_channels);
350     av_log(ctx, AV_LOG_INFO, "Bit depth: %u\n", bit_depth(mask));
351     av_log(ctx, AV_LOG_INFO, "Number of samples: %"PRId64"\n", nb_samples / s->nb_channels);
352 }
353
354 static av_cold void uninit(AVFilterContext *ctx)
355 {
356     AudioStatsContext *s = ctx->priv;
357
358     if (s->nb_channels)
359         print_stats(ctx);
360     av_freep(&s->chstats);
361 }
362
363 static const AVFilterPad astats_inputs[] = {
364     {
365         .name         = "default",
366         .type         = AVMEDIA_TYPE_AUDIO,
367         .filter_frame = filter_frame,
368     },
369     { NULL }
370 };
371
372 static const AVFilterPad astats_outputs[] = {
373     {
374         .name         = "default",
375         .type         = AVMEDIA_TYPE_AUDIO,
376         .config_props = config_output,
377     },
378     { NULL }
379 };
380
381 AVFilter ff_af_astats = {
382     .name          = "astats",
383     .description   = NULL_IF_CONFIG_SMALL("Show time domain statistics about audio frames."),
384     .query_formats = query_formats,
385     .priv_size     = sizeof(AudioStatsContext),
386     .priv_class    = &astats_class,
387     .uninit        = uninit,
388     .inputs        = astats_inputs,
389     .outputs       = astats_outputs,
390 };