FFmpeg
af_volumedetect.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Nicolas George
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 License
8  * 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
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
22 #include "libavutil/avassert.h"
23 #include "audio.h"
24 #include "avfilter.h"
25 #include "internal.h"
26 
27 typedef struct VolDetectContext {
28  /**
29  * Number of samples at each PCM value.
30  * histogram[0x8000 + i] is the number of samples at value i.
31  * The extra element is there for symmetry.
32  */
33  uint64_t histogram[0x10001];
35 
37 {
38  AVFilterContext *ctx = inlink->dst;
39  VolDetectContext *vd = ctx->priv;
40  int nb_samples = samples->nb_samples;
41  int nb_channels = samples->ch_layout.nb_channels;
42  int nb_planes = nb_channels;
43  int plane, i;
44  int16_t *pcm;
45 
46  if (!av_sample_fmt_is_planar(samples->format)) {
47  nb_samples *= nb_channels;
48  nb_planes = 1;
49  }
50  for (plane = 0; plane < nb_planes; plane++) {
51  pcm = (int16_t *)samples->extended_data[plane];
52  for (i = 0; i < nb_samples; i++)
53  vd->histogram[pcm[i] + 0x8000]++;
54  }
55 
56  return ff_filter_frame(inlink->dst->outputs[0], samples);
57 }
58 
59 #define MAX_DB 91
60 
61 static inline double logdb(uint64_t v)
62 {
63  double d = v / (double)(0x8000 * 0x8000);
64  if (!v)
65  return MAX_DB;
66  return -log10(d) * 10;
67 }
68 
70 {
71  VolDetectContext *vd = ctx->priv;
72  int i, max_volume, shift;
73  uint64_t nb_samples = 0, power = 0, nb_samples_shift = 0, sum = 0;
74  uint64_t histdb[MAX_DB + 1] = { 0 };
75 
76  for (i = 0; i < 0x10000; i++)
77  nb_samples += vd->histogram[i];
78  av_log(ctx, AV_LOG_INFO, "n_samples: %"PRId64"\n", nb_samples);
79  if (!nb_samples)
80  return;
81 
82  /* If nb_samples > 1<<34, there is a risk of overflow in the
83  multiplication or the sum: shift all histogram values to avoid that.
84  The total number of samples must be recomputed to avoid rounding
85  errors. */
86  shift = av_log2(nb_samples >> 33);
87  for (i = 0; i < 0x10000; i++) {
88  nb_samples_shift += vd->histogram[i] >> shift;
89  power += (i - 0x8000) * (i - 0x8000) * (vd->histogram[i] >> shift);
90  }
91  if (!nb_samples_shift)
92  return;
93  power = (power + nb_samples_shift / 2) / nb_samples_shift;
94  av_assert0(power <= 0x8000 * 0x8000);
95  av_log(ctx, AV_LOG_INFO, "mean_volume: %.1f dB\n", -logdb(power));
96 
97  max_volume = 0x8000;
98  while (max_volume > 0 && !vd->histogram[0x8000 + max_volume] &&
99  !vd->histogram[0x8000 - max_volume])
100  max_volume--;
101  av_log(ctx, AV_LOG_INFO, "max_volume: %.1f dB\n", -logdb(max_volume * max_volume));
102 
103  for (i = 0; i < 0x10000; i++)
104  histdb[(int)logdb((i - 0x8000) * (i - 0x8000))] += vd->histogram[i];
105  for (i = 0; i <= MAX_DB && !histdb[i]; i++);
106  for (; i <= MAX_DB && sum < nb_samples / 1000; i++) {
107  av_log(ctx, AV_LOG_INFO, "histogram_%ddb: %"PRId64"\n", i, histdb[i]);
108  sum += histdb[i];
109  }
110 }
111 
113 {
114  print_stats(ctx);
115 }
116 
118  {
119  .name = "default",
120  .type = AVMEDIA_TYPE_AUDIO,
121  .filter_frame = filter_frame,
122  },
123 };
124 
126  .name = "volumedetect",
127  .description = NULL_IF_CONFIG_SMALL("Detect audio volume."),
128  .priv_size = sizeof(VolDetectContext),
129  .uninit = uninit,
134 };
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_volumedetect.c:112
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:978
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
MAX_DB
#define MAX_DB
Definition: af_volumedetect.c:59
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
VolDetectContext::histogram
uint64_t histogram[0x10001]
Number of samples at each PCM value.
Definition: af_volumedetect.c:33
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:47
avassert.h
av_cold
#define av_cold
Definition: attributes.h:90
ff_af_volumedetect
const AVFilter ff_af_volumedetect
Definition: af_volumedetect.c:125
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
av_sample_fmt_is_planar
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:114
ctx
AVFormatContext * ctx
Definition: movenc.c:48
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:192
ff_audio_default_filterpad
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
Definition: audio.c:32
double
double
Definition: af_crystalizer.c:131
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:106
shift
static int shift(int a, int b)
Definition: bonk.c:262
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
AV_SAMPLE_FMT_S16P
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: samplefmt.h:64
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
internal.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *samples)
Definition: af_volumedetect.c:36
AV_SAMPLE_FMT_S16
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition: samplefmt.h:58
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:53
AVFilter
Filter definition.
Definition: avfilter.h:166
power
static float power(float r, float g, float b, float max)
Definition: preserve_color.h:45
channel_layout.h
avfilter.h
AVFILTER_FLAG_METADATA_ONLY
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
Definition: avfilter.h:133
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
logdb
static double logdb(uint64_t v)
Definition: af_volumedetect.c:61
AVFilterContext
An instance of a filter.
Definition: avfilter.h:397
VolDetectContext
Definition: af_volumedetect.c:27
audio.h
print_stats
static void print_stats(AVFilterContext *ctx)
Definition: af_volumedetect.c:69
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:193
d
d
Definition: ffmpeg_filter.c:368
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
FILTER_SAMPLEFMTS
#define FILTER_SAMPLEFMTS(...)
Definition: internal.h:180
volumedetect_inputs
static const AVFilterPad volumedetect_inputs[]
Definition: af_volumedetect.c:117