2 * Copyright (c) 2012 Clément Bœsch
4 * This file is part of FFmpeg.
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.
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.
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
23 * EBU R.128 implementation
24 * @see http://tech.ebu.ch/loudness
25 * @see https://www.youtube.com/watch?v=iuEtQqC-Sqo "EBU R128 Introduction - Florian Camerer"
26 * @todo implement start/stop/reset through filter command injection
32 #include "libavutil/avassert.h"
33 #include "libavutil/channel_layout.h"
34 #include "libavutil/dict.h"
35 #include "libavutil/ffmath.h"
36 #include "libavutil/mem.h"
37 #include "libavutil/xga_font_data.h"
38 #include "libavutil/opt.h"
39 #include "libavutil/timestamp.h"
40 #include "libswresample/swresample.h"
46 #define ABS_THRES -70 ///< silence gate: we discard anything below this absolute (LUFS) threshold
47 #define ABS_UP_THRES 10 ///< upper loud limit to consider (ABS_THRES being the minimum)
48 #define HIST_GRAIN 100 ///< defines histogram precision
49 #define HIST_SIZE ((ABS_UP_THRES - ABS_THRES) * HIST_GRAIN + 1)
52 * A histogram is an array of HIST_SIZE hist_entry storing all the energies
53 * recorded (with an accuracy of 1/HIST_GRAIN) of the loudnesses from ABS_THRES
54 * (at 0) to ABS_UP_THRES (at HIST_SIZE-1).
55 * This fixed-size system avoids the need of a list of energies growing
56 * infinitely over the time and is thus more scalable.
59 unsigned count
; ///< how many times the corresponding value occurred
60 double energy
; ///< E = 10^((L + 0.691) / 10)
61 double loudness
; ///< L = -0.691 + 10 * log10(E)
65 double **cache
; ///< window of filtered samples (N ms)
66 int cache_pos
; ///< focus on the last added bin in the cache array
68 double *sum
; ///< sum of the last N ms filtered samples (cache content)
69 int filled
; ///< 1 if the cache is completely filled, 0 otherwise
70 double rel_threshold
; ///< relative threshold
71 double sum_kept_powers
; ///< sum of the powers (weighted sums) above absolute threshold
72 int nb_kept_powers
; ///< number of sum above absolute threshold
73 struct hist_entry
*histogram
; ///< histogram of the powers, used to compute LRA and I
76 struct rect
{ int x
, y
, w
, h
; };
78 typedef struct EBUR128Context
{
79 const AVClass
*class; ///< AVClass context for log and options purpose
82 int peak_mode
; ///< enabled peak modes
83 double true_peak
; ///< global true peak
84 double *true_peaks
; ///< true peaks per channel
85 double sample_peak
; ///< global sample peak
86 double *sample_peaks
; ///< sample peaks per channel
87 double *true_peaks_per_frame
; ///< true peaks in a frame per channel
89 SwrContext
*swr_ctx
; ///< over-sampling context for true peak metering
90 double *swr_buf
; ///< resampled audio data for true peak metering
95 int do_video
; ///< 1 if video output enabled, 0 otherwise
96 int w
, h
; ///< size of the video output
97 struct rect text
; ///< rectangle for the LU legend on the left
98 struct rect graph
; ///< rectangle for the main graph in the center
99 struct rect gauge
; ///< rectangle for the gauge on the right
100 AVFrame
*outpicref
; ///< output picture reference, updated regularly
101 int meter
; ///< select a EBU mode between +9 and +18
102 int scale_range
; ///< the range of LU values according to the meter
103 int y_zero_lu
; ///< the y value (pixel position) for 0 LU
104 int y_opt_max
; ///< the y value (pixel position) for 1 LU
105 int y_opt_min
; ///< the y value (pixel position) for -1 LU
106 int *y_line_ref
; ///< y reference values for drawing the LU lines in the graph and the gauge
109 int nb_channels
; ///< number of channels in the input
110 double *ch_weighting
; ///< channel weighting mapping
111 int sample_count
; ///< sample count used for refresh frequency, reset at refresh
112 int nb_samples
; ///< number of samples to consume per single input frame
113 int idx_insample
; ///< current sample position of processed samples in single input frame
114 AVFrame
*insamples
; ///< input samples reference, updated regularly
117 * The mult by 3 in the following is for X[i], X[i-1] and X[i-2] */
118 double *x
; ///< 3 input samples cache for each channel
119 double *y
; ///< 3 pre-filter samples cache for each channel
120 double *z
; ///< 3 RLB-filter samples cache for each channel
121 double pre_b
[3]; ///< pre-filter numerator coefficients
122 double pre_a
[3]; ///< pre-filter denominator coefficients
123 double rlb_b
[3]; ///< rlb-filter numerator coefficients
124 double rlb_a
[3]; ///< rlb-filter denominator coefficients
126 struct integrator i400
; ///< 400ms integrator, used for Momentary loudness (M), and Integrated loudness (I)
127 struct integrator i3000
; ///< 3s integrator, used for Short term loudness (S), and Loudness Range (LRA)
129 /* I and LRA specific */
130 double integrated_loudness
; ///< integrated loudness in LUFS (I)
131 double loudness_range
; ///< loudness range in LU (LRA)
132 double lra_low
, lra_high
; ///< low and high LRA values
135 int loglevel
; ///< log level for frame logging
136 int metadata
; ///< whether or not to inject loudness results in frames
137 int dual_mono
; ///< whether or not to treat single channel input files as dual-mono
138 double pan_law
; ///< pan law value used to calculate dual-mono measurements
139 int target
; ///< target level in LUFS used to set relative zero LU in visualization
140 int gauge_type
; ///< whether gauge shows momentary or short
141 int scale
; ///< display scale type of statistics
146 PEAK_MODE_SAMPLES_PEAKS
= 1<<1,
147 PEAK_MODE_TRUE_PEAKS
= 1<<2,
151 GAUGE_TYPE_MOMENTARY
= 0,
152 GAUGE_TYPE_SHORTTERM
= 1,
156 SCALE_TYPE_ABSOLUTE
= 0,
157 SCALE_TYPE_RELATIVE
= 1,
160 #define OFFSET(x) offsetof(EBUR128Context, x)
161 #define A AV_OPT_FLAG_AUDIO_PARAM
162 #define V AV_OPT_FLAG_VIDEO_PARAM
163 #define F AV_OPT_FLAG_FILTERING_PARAM
164 #define X AV_OPT_FLAG_EXPORT
165 #define R AV_OPT_FLAG_READONLY
166 static const AVOption ebur128_options
[] = {
167 { "video", "set video output", OFFSET(do_video
), AV_OPT_TYPE_BOOL
, {.i64
= 0}, 0, 1, V
|F
},
168 { "size", "set video size", OFFSET(w
), AV_OPT_TYPE_IMAGE_SIZE
, {.str
= "640x480"}, 0, 0, V
|F
},
169 { "meter", "set scale meter (+9 to +18)", OFFSET(meter
), AV_OPT_TYPE_INT
, {.i64
= 9}, 9, 18, V
|F
},
170 { "framelog", "force frame logging level", OFFSET(loglevel
), AV_OPT_TYPE_INT
, {.i64
= -1}, INT_MIN
, INT_MAX
, A
|V
|F
, .unit
= "level" },
171 { "quiet", "logging disabled", 0, AV_OPT_TYPE_CONST
, {.i64
= AV_LOG_QUIET
}, INT_MIN
, INT_MAX
, A
|V
|F
, .unit
= "level" },
172 { "info", "information logging level", 0, AV_OPT_TYPE_CONST
, {.i64
= AV_LOG_INFO
}, INT_MIN
, INT_MAX
, A
|V
|F
, .unit
= "level" },
173 { "verbose", "verbose logging level", 0, AV_OPT_TYPE_CONST
, {.i64
= AV_LOG_VERBOSE
}, INT_MIN
, INT_MAX
, A
|V
|F
, .unit
= "level" },
174 { "metadata", "inject metadata in the filtergraph", OFFSET(metadata
), AV_OPT_TYPE_BOOL
, {.i64
= 0}, 0, 1, A
|V
|F
},
175 { "peak", "set peak mode", OFFSET(peak_mode
), AV_OPT_TYPE_FLAGS
, {.i64
= PEAK_MODE_NONE
}, 0, INT_MAX
, A
|F
, .unit
= "mode" },
176 { "none", "disable any peak mode", 0, AV_OPT_TYPE_CONST
, {.i64
= PEAK_MODE_NONE
}, INT_MIN
, INT_MAX
, A
|F
, .unit
= "mode" },
177 { "sample", "enable peak-sample mode", 0, AV_OPT_TYPE_CONST
, {.i64
= PEAK_MODE_SAMPLES_PEAKS
}, INT_MIN
, INT_MAX
, A
|F
, .unit
= "mode" },
178 { "true", "enable true-peak mode", 0, AV_OPT_TYPE_CONST
, {.i64
= PEAK_MODE_TRUE_PEAKS
}, INT_MIN
, INT_MAX
, A
|F
, .unit
= "mode" },
179 { "dualmono", "treat mono input files as dual-mono", OFFSET(dual_mono
), AV_OPT_TYPE_BOOL
, {.i64
= 0}, 0, 1, A
|F
},
180 { "panlaw", "set a specific pan law for dual-mono files", OFFSET(pan_law
), AV_OPT_TYPE_DOUBLE
, {.dbl
= -3.01029995663978}, -10.0, 0.0, A
|F
},
181 { "target", "set a specific target level in LUFS (-23 to 0)", OFFSET(target
), AV_OPT_TYPE_INT
, {.i64
= -23}, -23, 0, V
|F
},
182 { "gauge", "set gauge display type", OFFSET(gauge_type
), AV_OPT_TYPE_INT
, {.i64
= 0 }, GAUGE_TYPE_MOMENTARY
, GAUGE_TYPE_SHORTTERM
, V
|F
, .unit
= "gaugetype" },
183 { "momentary", "display momentary value", 0, AV_OPT_TYPE_CONST
, {.i64
= GAUGE_TYPE_MOMENTARY
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "gaugetype" },
184 { "m", "display momentary value", 0, AV_OPT_TYPE_CONST
, {.i64
= GAUGE_TYPE_MOMENTARY
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "gaugetype" },
185 { "shortterm", "display short-term value", 0, AV_OPT_TYPE_CONST
, {.i64
= GAUGE_TYPE_SHORTTERM
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "gaugetype" },
186 { "s", "display short-term value", 0, AV_OPT_TYPE_CONST
, {.i64
= GAUGE_TYPE_SHORTTERM
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "gaugetype" },
187 { "scale", "sets display method for the stats", OFFSET(scale
), AV_OPT_TYPE_INT
, {.i64
= 0}, SCALE_TYPE_ABSOLUTE
, SCALE_TYPE_RELATIVE
, V
|F
, .unit
= "scaletype" },
188 { "absolute", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST
, {.i64
= SCALE_TYPE_ABSOLUTE
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "scaletype" },
189 { "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST
, {.i64
= SCALE_TYPE_ABSOLUTE
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "scaletype" },
190 { "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST
, {.i64
= SCALE_TYPE_RELATIVE
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "scaletype" },
191 { "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST
, {.i64
= SCALE_TYPE_RELATIVE
}, INT_MIN
, INT_MAX
, V
|F
, .unit
= "scaletype" },
192 { "integrated", "integrated loudness (LUFS)", OFFSET(integrated_loudness
), AV_OPT_TYPE_DOUBLE
, {.dbl
= 0}, -DBL_MAX
, DBL_MAX
, A
|F
|X
|R
},
193 { "range", "loudness range (LU)", OFFSET(loudness_range
), AV_OPT_TYPE_DOUBLE
, {.dbl
= 0}, -DBL_MAX
, DBL_MAX
, A
|F
|X
|R
},
194 { "lra_low", "LRA low (LUFS)", OFFSET(lra_low
), AV_OPT_TYPE_DOUBLE
, {.dbl
= 0}, -DBL_MAX
, DBL_MAX
, A
|F
|X
|R
},
195 { "lra_high", "LRA high (LUFS)", OFFSET(lra_high
), AV_OPT_TYPE_DOUBLE
, {.dbl
= 0}, -DBL_MAX
, DBL_MAX
, A
|F
|X
|R
},
196 { "sample_peak", "sample peak (dBFS)", OFFSET(sample_peak
), AV_OPT_TYPE_DOUBLE
, {.dbl
= 0}, -DBL_MAX
, DBL_MAX
, A
|F
|X
|R
},
197 { "true_peak", "true peak (dBFS)", OFFSET(true_peak
), AV_OPT_TYPE_DOUBLE
, {.dbl
= 0}, -DBL_MAX
, DBL_MAX
, A
|F
|X
|R
},
201 AVFILTER_DEFINE_CLASS(ebur128
);
203 static const uint8_t graph_colors
[] = {
204 0xdd, 0x66, 0x66, // value above 1LU non reached below -1LU (impossible)
205 0x66, 0x66, 0xdd, // value below 1LU non reached below -1LU
206 0x96, 0x33, 0x33, // value above 1LU reached below -1LU (impossible)
207 0x33, 0x33, 0x96, // value below 1LU reached below -1LU
208 0xdd, 0x96, 0x96, // value above 1LU line non reached below -1LU (impossible)
209 0x96, 0x96, 0xdd, // value below 1LU line non reached below -1LU
210 0xdd, 0x33, 0x33, // value above 1LU line reached below -1LU (impossible)
211 0x33, 0x33, 0xdd, // value below 1LU line reached below -1LU
212 0xdd, 0x66, 0x66, // value above 1LU non reached above -1LU
213 0x66, 0xdd, 0x66, // value below 1LU non reached above -1LU
214 0x96, 0x33, 0x33, // value above 1LU reached above -1LU
215 0x33, 0x96, 0x33, // value below 1LU reached above -1LU
216 0xdd, 0x96, 0x96, // value above 1LU line non reached above -1LU
217 0x96, 0xdd, 0x96, // value below 1LU line non reached above -1LU
218 0xdd, 0x33, 0x33, // value above 1LU line reached above -1LU
219 0x33, 0xdd, 0x33, // value below 1LU line reached above -1LU
222 static const uint8_t *get_graph_color(const EBUR128Context
*ebur128
, int v
, int y
)
224 const int above_opt_max
= y
> ebur128
->y_opt_max
;
225 const int below_opt_min
= y
< ebur128
->y_opt_min
;
226 const int reached
= y
>= v
;
227 const int line
= ebur128
->y_line_ref
[y
] || y
== ebur128
->y_zero_lu
;
228 const int colorid
= 8*below_opt_min
+ 4*line
+ 2*reached
+ above_opt_max
;
229 return graph_colors
+ 3*colorid
;
232 static inline int lu_to_y(const EBUR128Context
*ebur128
, double v
)
234 v
+= 2 * ebur128
->meter
; // make it in range [0;...]
235 v
= av_clipf(v
, 0, ebur128
->scale_range
); // make sure it's in the graph scale
236 v
= ebur128
->scale_range
- v
; // invert value (y=0 is on top)
237 return v
* ebur128
->graph
.h
/ ebur128
->scale_range
; // rescale from scale range to px height
243 static const uint8_t font_colors
[] = {
248 static void drawtext(AVFrame
*pic
, int x
, int y
, int ftid
, const uint8_t *color
, const char *fmt
, ...)
256 if (ftid
== FONT16
) font
= avpriv_vga16_font
, font_height
= 16;
257 else if (ftid
== FONT8
) font
= avpriv_cga_font
, font_height
= 8;
261 vsnprintf(buf
, sizeof(buf
), fmt
, vl
);
264 for (i
= 0; buf
[i
]; i
++) {
266 uint8_t *p
= pic
->data
[0] + y
*pic
->linesize
[0] + (x
+ i
*8)*3;
268 for (char_y
= 0; char_y
< font_height
; char_y
++) {
269 for (mask
= 0x80; mask
; mask
>>= 1) {
270 if (font
[buf
[i
] * font_height
+ char_y
] & mask
)
273 memcpy(p
, "\x00\x00\x00", 3);
276 p
+= pic
->linesize
[0] - 8*3;
281 static void drawline(AVFrame
*pic
, int x
, int y
, int len
, int step
)
284 uint8_t *p
= pic
->data
[0] + y
*pic
->linesize
[0] + x
*3;
286 for (i
= 0; i
< len
; i
++) {
287 memcpy(p
, "\x00\xff\x00", 3);
292 static int config_video_output(AVFilterLink
*outlink
)
296 FilterLink
*l
= ff_filter_link(outlink
);
297 AVFilterContext
*ctx
= outlink
->src
;
298 EBUR128Context
*ebur128
= ctx
->priv
;
301 /* check if there is enough space to represent everything decently */
302 if (ebur128
->w
< 640 || ebur128
->h
< 480) {
303 av_log(ctx
, AV_LOG_ERROR
, "Video size %dx%d is too small, "
304 "minimum size is 640x480\n", ebur128
->w
, ebur128
->h
);
305 return AVERROR(EINVAL
);
307 outlink
->w
= ebur128
->w
;
308 outlink
->h
= ebur128
->h
;
309 outlink
->sample_aspect_ratio
= (AVRational
){1,1};
310 l
->frame_rate
= av_make_q(10, 1);
311 outlink
->time_base
= av_inv_q(l
->frame_rate
);
315 /* configure text area position and size */
316 ebur128
->text
.x
= PAD
;
317 ebur128
->text
.y
= 40;
318 ebur128
->text
.w
= 3 * 8; // 3 characters
319 ebur128
->text
.h
= ebur128
->h
- PAD
- ebur128
->text
.y
;
321 /* configure gauge position and size */
322 ebur128
->gauge
.w
= 20;
323 ebur128
->gauge
.h
= ebur128
->text
.h
;
324 ebur128
->gauge
.x
= ebur128
->w
- PAD
- ebur128
->gauge
.w
;
325 ebur128
->gauge
.y
= ebur128
->text
.y
;
327 /* configure graph position and size */
328 ebur128
->graph
.x
= ebur128
->text
.x
+ ebur128
->text
.w
+ PAD
;
329 ebur128
->graph
.y
= ebur128
->gauge
.y
;
330 ebur128
->graph
.w
= ebur128
->gauge
.x
- ebur128
->graph
.x
- PAD
;
331 ebur128
->graph
.h
= ebur128
->gauge
.h
;
333 /* graph and gauge share the LU-to-pixel code */
334 av_assert0(ebur128
->graph
.h
== ebur128
->gauge
.h
);
336 /* prepare the initial picref buffer */
337 av_frame_free(&ebur128
->outpicref
);
338 ebur128
->outpicref
= outpicref
=
339 ff_get_video_buffer(outlink
, outlink
->w
, outlink
->h
);
341 return AVERROR(ENOMEM
);
342 outpicref
->sample_aspect_ratio
= (AVRational
){1,1};
344 /* init y references values (to draw LU lines) */
345 ebur128
->y_line_ref
= av_calloc(ebur128
->graph
.h
+ 1, sizeof(*ebur128
->y_line_ref
));
346 if (!ebur128
->y_line_ref
)
347 return AVERROR(ENOMEM
);
349 /* black background */
350 for (int y
= 0; y
< ebur128
->h
; y
++)
351 memset(outpicref
->data
[0] + y
* outpicref
->linesize
[0], 0, ebur128
->w
* 3);
353 /* draw LU legends */
354 drawtext(outpicref
, PAD
, PAD
+16, FONT8
, font_colors
+3, " LU");
355 for (i
= ebur128
->meter
; i
>= -ebur128
->meter
* 2; i
--) {
356 y
= lu_to_y(ebur128
, i
);
357 x
= PAD
+ (i
< 10 && i
> -10) * 8;
358 ebur128
->y_line_ref
[y
] = i
;
359 y
-= 4; // -4 to center vertically
360 drawtext(outpicref
, x
, y
+ ebur128
->graph
.y
, FONT8
, font_colors
+3,
361 "%c%d", i
< 0 ? '-' : i
> 0 ? '+' : ' ', FFABS(i
));
365 ebur128
->y_zero_lu
= lu_to_y(ebur128
, 0);
366 ebur128
->y_opt_max
= lu_to_y(ebur128
, 1);
367 ebur128
->y_opt_min
= lu_to_y(ebur128
, -1);
368 p
= outpicref
->data
[0] + ebur128
->graph
.y
* outpicref
->linesize
[0]
369 + ebur128
->graph
.x
* 3;
370 for (y
= 0; y
< ebur128
->graph
.h
; y
++) {
371 const uint8_t *c
= get_graph_color(ebur128
, INT_MAX
, y
);
373 for (x
= 0; x
< ebur128
->graph
.w
; x
++)
374 memcpy(p
+ x
*3, c
, 3);
375 p
+= outpicref
->linesize
[0];
378 /* draw fancy rectangles around the graph and the gauge */
379 #define DRAW_RECT(r) do { \
380 drawline(outpicref, r.x, r.y - 1, r.w, 3); \
381 drawline(outpicref, r.x, r.y + r.h, r.w, 3); \
382 drawline(outpicref, r.x - 1, r.y, r.h, outpicref->linesize[0]); \
383 drawline(outpicref, r.x + r.w, r.y, r.h, outpicref->linesize[0]); \
385 DRAW_RECT(ebur128
->graph
);
386 DRAW_RECT(ebur128
->gauge
);
391 static int config_audio_input(AVFilterLink
*inlink
)
393 AVFilterContext
*ctx
= inlink
->dst
;
394 EBUR128Context
*ebur128
= ctx
->priv
;
396 /* Unofficial reversed parametrization of PRE
397 * and RLB from 48kHz */
399 double f0
= 1681.974450955533;
400 double G
= 3.999843853973347;
401 double Q
= 0.7071752369554196;
403 double K
= tan(M_PI
* f0
/ (double)inlink
->sample_rate
);
404 double Vh
= pow(10.0, G
/ 20.0);
405 double Vb
= pow(Vh
, 0.4996667741545416);
407 double a0
= 1.0 + K
/ Q
+ K
* K
;
409 ebur128
->pre_b
[0] = (Vh
+ Vb
* K
/ Q
+ K
* K
) / a0
;
410 ebur128
->pre_b
[1] = 2.0 * (K
* K
- Vh
) / a0
;
411 ebur128
->pre_b
[2] = (Vh
- Vb
* K
/ Q
+ K
* K
) / a0
;
412 ebur128
->pre_a
[1] = 2.0 * (K
* K
- 1.0) / a0
;
413 ebur128
->pre_a
[2] = (1.0 - K
/ Q
+ K
* K
) / a0
;
415 f0
= 38.13547087602444;
416 Q
= 0.5003270373238773;
417 K
= tan(M_PI
* f0
/ (double)inlink
->sample_rate
);
419 ebur128
->rlb_b
[0] = 1.0;
420 ebur128
->rlb_b
[1] = -2.0;
421 ebur128
->rlb_b
[2] = 1.0;
422 ebur128
->rlb_a
[1] = 2.0 * (K
* K
- 1.0) / (1.0 + K
/ Q
+ K
* K
);
423 ebur128
->rlb_a
[2] = (1.0 - K
/ Q
+ K
* K
) / (1.0 + K
/ Q
+ K
* K
);
425 /* Force 100ms framing in case of metadata injection: the frames must have
426 * a granularity of the window overlap to be accurately exploited.
427 * As for the true peaks mode, it just simplifies the resampling buffer
428 * allocation and the lookup in it (since sample buffers differ in size, it
429 * can be more complex to integrate in the one-sample loop of
430 * filter_frame()). */
431 if (ebur128
->metadata
|| (ebur128
->peak_mode
& PEAK_MODE_TRUE_PEAKS
))
432 ebur128
->nb_samples
= FFMAX(inlink
->sample_rate
/ 10, 1);
436 static int config_audio_output(AVFilterLink
*outlink
)
439 AVFilterContext
*ctx
= outlink
->src
;
440 EBUR128Context
*ebur128
= ctx
->priv
;
441 const int nb_channels
= outlink
->ch_layout
.nb_channels
;
443 #define BACK_MASK (AV_CH_BACK_LEFT |AV_CH_BACK_CENTER |AV_CH_BACK_RIGHT| \
444 AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_BACK_RIGHT| \
445 AV_CH_SIDE_LEFT |AV_CH_SIDE_RIGHT| \
446 AV_CH_SURROUND_DIRECT_LEFT |AV_CH_SURROUND_DIRECT_RIGHT)
448 ebur128
->nb_channels
= nb_channels
;
449 ebur128
->x
= av_calloc(nb_channels
, 3 * sizeof(*ebur128
->x
));
450 ebur128
->y
= av_calloc(nb_channels
, 3 * sizeof(*ebur128
->y
));
451 ebur128
->z
= av_calloc(nb_channels
, 3 * sizeof(*ebur128
->z
));
452 ebur128
->ch_weighting
= av_calloc(nb_channels
, sizeof(*ebur128
->ch_weighting
));
453 if (!ebur128
->ch_weighting
|| !ebur128
->x
|| !ebur128
->y
|| !ebur128
->z
)
454 return AVERROR(ENOMEM
);
456 #define I400_BINS(x) ((x) * 4 / 10)
457 #define I3000_BINS(x) ((x) * 3)
459 ebur128
->i400
.sum
= av_calloc(nb_channels
, sizeof(*ebur128
->i400
.sum
));
460 ebur128
->i3000
.sum
= av_calloc(nb_channels
, sizeof(*ebur128
->i3000
.sum
));
461 ebur128
->i400
.cache
= av_calloc(nb_channels
, sizeof(*ebur128
->i400
.cache
));
462 ebur128
->i3000
.cache
= av_calloc(nb_channels
, sizeof(*ebur128
->i3000
.cache
));
463 if (!ebur128
->i400
.sum
|| !ebur128
->i3000
.sum
||
464 !ebur128
->i400
.cache
|| !ebur128
->i3000
.cache
)
465 return AVERROR(ENOMEM
);
467 for (i
= 0; i
< nb_channels
; i
++) {
468 /* channel weighting */
469 const enum AVChannel chl
= av_channel_layout_channel_from_index(&outlink
->ch_layout
, i
);
470 if (chl
== AV_CHAN_LOW_FREQUENCY
|| chl
== AV_CHAN_LOW_FREQUENCY_2
) {
471 ebur128
->ch_weighting
[i
] = 0;
472 } else if (chl
< 64 && (1ULL << chl
) & BACK_MASK
) {
473 ebur128
->ch_weighting
[i
] = 1.41;
475 ebur128
->ch_weighting
[i
] = 1.0;
478 if (!ebur128
->ch_weighting
[i
])
481 /* bins buffer for the two integration window (400ms and 3s) */
482 ebur128
->i400
.cache_size
= I400_BINS(outlink
->sample_rate
);
483 ebur128
->i3000
.cache_size
= I3000_BINS(outlink
->sample_rate
);
484 ebur128
->i400
.cache
[i
] = av_calloc(ebur128
->i400
.cache_size
, sizeof(*ebur128
->i400
.cache
[0]));
485 ebur128
->i3000
.cache
[i
] = av_calloc(ebur128
->i3000
.cache_size
, sizeof(*ebur128
->i3000
.cache
[0]));
486 if (!ebur128
->i400
.cache
[i
] || !ebur128
->i3000
.cache
[i
])
487 return AVERROR(ENOMEM
);
490 #if CONFIG_SWRESAMPLE
491 if (ebur128
->peak_mode
& PEAK_MODE_TRUE_PEAKS
) {
494 ebur128
->swr_buf
= av_malloc_array(nb_channels
, 19200 * sizeof(double));
495 ebur128
->true_peaks
= av_calloc(nb_channels
, sizeof(*ebur128
->true_peaks
));
496 ebur128
->true_peaks_per_frame
= av_calloc(nb_channels
, sizeof(*ebur128
->true_peaks_per_frame
));
497 ebur128
->swr_ctx
= swr_alloc();
498 if (!ebur128
->swr_buf
|| !ebur128
->true_peaks
||
499 !ebur128
->true_peaks_per_frame
|| !ebur128
->swr_ctx
)
500 return AVERROR(ENOMEM
);
502 av_opt_set_chlayout(ebur128
->swr_ctx
, "in_chlayout", &outlink
->ch_layout
, 0);
503 av_opt_set_int(ebur128
->swr_ctx
, "in_sample_rate", outlink
->sample_rate
, 0);
504 av_opt_set_sample_fmt(ebur128
->swr_ctx
, "in_sample_fmt", outlink
->format
, 0);
506 av_opt_set_chlayout(ebur128
->swr_ctx
, "out_chlayout", &outlink
->ch_layout
, 0);
507 av_opt_set_int(ebur128
->swr_ctx
, "out_sample_rate", 192000, 0);
508 av_opt_set_sample_fmt(ebur128
->swr_ctx
, "out_sample_fmt", outlink
->format
, 0);
510 ret
= swr_init(ebur128
->swr_ctx
);
516 if (ebur128
->peak_mode
& PEAK_MODE_SAMPLES_PEAKS
) {
517 ebur128
->sample_peaks
= av_calloc(nb_channels
, sizeof(*ebur128
->sample_peaks
));
518 if (!ebur128
->sample_peaks
)
519 return AVERROR(ENOMEM
);
525 #define ENERGY(loudness) (ff_exp10(((loudness) + 0.691) / 10.))
526 #define LOUDNESS(energy) (-0.691 + 10 * log10(energy))
527 #define DBFS(energy) (20 * log10(energy))
529 static struct hist_entry
*get_histogram(void)
532 struct hist_entry
*h
= av_calloc(HIST_SIZE
, sizeof(*h
));
536 for (i
= 0; i
< HIST_SIZE
; i
++) {
537 h
[i
].loudness
= i
/ (double)HIST_GRAIN
+ ABS_THRES
;
538 h
[i
].energy
= ENERGY(h
[i
].loudness
);
543 static av_cold
int init(AVFilterContext
*ctx
)
545 EBUR128Context
*ebur128
= ctx
->priv
;
549 if (ebur128
->loglevel
!= AV_LOG_INFO
&&
550 ebur128
->loglevel
!= AV_LOG_QUIET
&&
551 ebur128
->loglevel
!= AV_LOG_VERBOSE
) {
552 if (ebur128
->do_video
|| ebur128
->metadata
)
553 ebur128
->loglevel
= AV_LOG_VERBOSE
;
555 ebur128
->loglevel
= AV_LOG_INFO
;
558 if (!CONFIG_SWRESAMPLE
&& (ebur128
->peak_mode
& PEAK_MODE_TRUE_PEAKS
)) {
559 av_log(ctx
, AV_LOG_ERROR
,
560 "True-peak mode requires libswresample to be performed\n");
561 return AVERROR(EINVAL
);
564 // if meter is +9 scale, scale range is from -18 LU to +9 LU (or 3*9)
565 // if meter is +18 scale, scale range is from -36 LU to +18 LU (or 3*18)
566 ebur128
->scale_range
= 3 * ebur128
->meter
;
568 ebur128
->i400
.histogram
= get_histogram();
569 ebur128
->i3000
.histogram
= get_histogram();
570 if (!ebur128
->i400
.histogram
|| !ebur128
->i3000
.histogram
)
571 return AVERROR(ENOMEM
);
573 ebur128
->integrated_loudness
= ABS_THRES
;
574 ebur128
->loudness_range
= 0;
576 /* insert output pads */
577 if (ebur128
->do_video
) {
580 .type
= AVMEDIA_TYPE_VIDEO
,
581 .config_props
= config_video_output
,
583 ret
= ff_append_outpad(ctx
, &pad
);
588 .name
= ebur128
->do_video
? "out1" : "out0",
589 .type
= AVMEDIA_TYPE_AUDIO
,
590 .config_props
= config_audio_output
,
592 ret
= ff_append_outpad(ctx
, &pad
);
597 av_log(ctx
, AV_LOG_VERBOSE
, "EBU +%d scale\n", ebur128
->meter
);
602 #define HIST_POS(power) (int)(((power) - ABS_THRES) * HIST_GRAIN)
604 /* loudness and power should be set such as loudness = -0.691 +
605 * 10*log10(power), we just avoid doing that calculus two times */
606 static int gate_update(struct integrator
*integ
, double power
,
607 double loudness
, int gate_thres
)
610 double relative_threshold
;
613 /* update powers histograms by incrementing current power count */
614 ipower
= av_clip(HIST_POS(loudness
), 0, HIST_SIZE
- 1);
615 integ
->histogram
[ipower
].count
++;
617 /* compute relative threshold and get its position in the histogram */
618 integ
->sum_kept_powers
+= power
;
619 integ
->nb_kept_powers
++;
620 relative_threshold
= integ
->sum_kept_powers
/ integ
->nb_kept_powers
;
621 if (!relative_threshold
)
622 relative_threshold
= 1e-12;
623 integ
->rel_threshold
= LOUDNESS(relative_threshold
) + gate_thres
;
624 gate_hist_pos
= av_clip(HIST_POS(integ
->rel_threshold
), 0, HIST_SIZE
- 1);
626 return gate_hist_pos
;
629 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*insamples
)
631 int i
, ch
, idx_insample
, ret
;
632 AVFilterContext
*ctx
= inlink
->dst
;
633 EBUR128Context
*ebur128
= ctx
->priv
;
634 const int nb_channels
= ebur128
->nb_channels
;
635 const int nb_samples
= insamples
->nb_samples
;
636 const double *samples
= (double *)insamples
->data
[0];
639 #if CONFIG_SWRESAMPLE
640 if (ebur128
->peak_mode
& PEAK_MODE_TRUE_PEAKS
&& ebur128
->idx_insample
== 0) {
641 const double *swr_samples
= ebur128
->swr_buf
;
642 int ret
= swr_convert(ebur128
->swr_ctx
, (uint8_t**)&ebur128
->swr_buf
, 19200,
643 (const uint8_t **)insamples
->data
, nb_samples
);
646 for (ch
= 0; ch
< nb_channels
; ch
++)
647 ebur128
->true_peaks_per_frame
[ch
] = 0.0;
648 for (idx_insample
= 0; idx_insample
< ret
; idx_insample
++) {
649 for (ch
= 0; ch
< nb_channels
; ch
++) {
650 ebur128
->true_peaks
[ch
] = FFMAX(ebur128
->true_peaks
[ch
], fabs(*swr_samples
));
651 ebur128
->true_peaks_per_frame
[ch
] = FFMAX(ebur128
->true_peaks_per_frame
[ch
],
659 for (idx_insample
= ebur128
->idx_insample
; idx_insample
< nb_samples
; idx_insample
++) {
660 const int bin_id_400
= ebur128
->i400
.cache_pos
;
661 const int bin_id_3000
= ebur128
->i3000
.cache_pos
;
663 #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \
664 ebur128->i##time.cache_pos++; \
665 if (ebur128->i##time.cache_pos == \
666 ebur128->i##time.cache_size) { \
667 ebur128->i##time.filled = 1; \
668 ebur128->i##time.cache_pos = 0; \
672 MOVE_TO_NEXT_CACHED_ENTRY(400);
673 MOVE_TO_NEXT_CACHED_ENTRY(3000);
675 for (ch
= 0; ch
< nb_channels
; ch
++) {
678 if (ebur128
->peak_mode
& PEAK_MODE_SAMPLES_PEAKS
)
679 ebur128
->sample_peaks
[ch
] = FFMAX(ebur128
->sample_peaks
[ch
], fabs(samples
[idx_insample
* nb_channels
+ ch
]));
681 ebur128
->x
[ch
* 3] = samples
[idx_insample
* nb_channels
+ ch
]; // set X[i]
683 if (!ebur128
->ch_weighting
[ch
])
686 /* Y[i] = X[i]*b0 + X[i-1]*b1 + X[i-2]*b2 - Y[i-1]*a1 - Y[i-2]*a2 */
687 #define FILTER(Y, X, NUM, DEN) do { \
688 double *dst = ebur128->Y + ch*3; \
689 double *src = ebur128->X + ch*3; \
692 dst[0] = src[0]*NUM[0] + src[1]*NUM[1] + src[2]*NUM[2] \
693 - dst[1]*DEN[1] - dst[2]*DEN[2]; \
696 // TODO: merge both filters in one?
697 FILTER(y
, x
, ebur128
->pre_b
, ebur128
->pre_a
); // apply pre-filter
698 ebur128
->x
[ch
* 3 + 2] = ebur128
->x
[ch
* 3 + 1];
699 ebur128
->x
[ch
* 3 + 1] = ebur128
->x
[ch
* 3 ];
700 FILTER(z
, y
, ebur128
->rlb_b
, ebur128
->rlb_a
); // apply RLB-filter
702 bin
= ebur128
->z
[ch
* 3] * ebur128
->z
[ch
* 3];
704 /* add the new value, and limit the sum to the cache size (400ms or 3s)
705 * by removing the oldest one */
706 ebur128
->i400
.sum
[ch
] = ebur128
->i400
.sum
[ch
] + bin
- ebur128
->i400
.cache
[ch
][bin_id_400
];
707 ebur128
->i3000
.sum
[ch
] = ebur128
->i3000
.sum
[ch
] + bin
- ebur128
->i3000
.cache
[ch
][bin_id_3000
];
709 /* override old cache entry with the new value */
710 ebur128
->i400
.cache
[ch
][bin_id_400
] = bin
;
711 ebur128
->i3000
.cache
[ch
][bin_id_3000
] = bin
;
714 #define FIND_PEAK(global, sp, ptype) do { \
718 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
719 for (ch = 0; ch < ebur128->nb_channels; ch++) \
720 maxpeak = FFMAX(maxpeak, sp[ch]); \
721 global = DBFS(maxpeak); \
725 FIND_PEAK(ebur128
->sample_peak
, ebur128
->sample_peaks
, SAMPLES
);
726 FIND_PEAK(ebur128
->true_peak
, ebur128
->true_peaks
, TRUE
);
728 /* For integrated loudness, gating blocks are 400ms long with 75%
729 * overlap (see BS.1770-2 p5), so a re-computation is needed each 100ms
730 * (4800 samples at 48kHz). */
731 if (++ebur128
->sample_count
== inlink
->sample_rate
/ 10) {
732 double loudness_400
, loudness_3000
;
733 double power_400
= 1e-12, power_3000
= 1e-12;
734 AVFilterLink
*outlink
= ctx
->outputs
[0];
735 const int64_t pts
= insamples
->pts
+
736 av_rescale_q(idx_insample
, (AVRational
){ 1, inlink
->sample_rate
},
737 ctx
->outputs
[ebur128
->do_video
]->time_base
);
739 ebur128
->sample_count
= 0;
741 #define COMPUTE_LOUDNESS(m, time) do { \
742 if (ebur128->i##time.filled) { \
743 /* weighting sum of the last <time> ms */ \
744 for (ch = 0; ch < nb_channels; ch++) \
745 power_##time += ebur128->ch_weighting[ch] * ebur128->i##time.sum[ch]; \
746 power_##time /= I##time##_BINS(inlink->sample_rate); \
748 loudness_##time = LOUDNESS(power_##time); \
751 COMPUTE_LOUDNESS(M
, 400);
752 COMPUTE_LOUDNESS(S
, 3000);
754 /* Integrated loudness */
755 #define I_GATE_THRES -10 // initially defined to -8 LU in the first EBU standard
757 if (loudness_400
>= ABS_THRES
) {
758 double integrated_sum
= 0.0;
759 uint64_t nb_integrated
= 0;
760 int gate_hist_pos
= gate_update(&ebur128
->i400
, power_400
,
761 loudness_400
, I_GATE_THRES
);
763 /* compute integrated loudness by summing the histogram values
764 * above the relative threshold */
765 for (i
= gate_hist_pos
; i
< HIST_SIZE
; i
++) {
766 const unsigned nb_v
= ebur128
->i400
.histogram
[i
].count
;
767 nb_integrated
+= nb_v
;
768 integrated_sum
+= nb_v
* ebur128
->i400
.histogram
[i
].energy
;
771 ebur128
->integrated_loudness
= LOUDNESS(integrated_sum
/ nb_integrated
);
772 /* dual-mono correction */
773 if (nb_channels
== 1 && ebur128
->dual_mono
) {
774 ebur128
->integrated_loudness
-= ebur128
->pan_law
;
780 #define LRA_GATE_THRES -20
781 #define LRA_LOWER_PRC 10
782 #define LRA_HIGHER_PRC 95
784 /* XXX: example code in EBU 3342 is ">=" but formula in BS.1770
786 if (loudness_3000
>= ABS_THRES
) {
787 uint64_t nb_powers
= 0;
788 int gate_hist_pos
= gate_update(&ebur128
->i3000
, power_3000
,
789 loudness_3000
, LRA_GATE_THRES
);
791 for (i
= gate_hist_pos
; i
< HIST_SIZE
; i
++)
792 nb_powers
+= ebur128
->i3000
.histogram
[i
].count
;
796 /* get lower loudness to consider */
798 nb_pow
= LRA_LOWER_PRC
* nb_powers
* 0.01 + 0.5;
799 for (i
= gate_hist_pos
; i
< HIST_SIZE
; i
++) {
800 n
+= ebur128
->i3000
.histogram
[i
].count
;
802 ebur128
->lra_low
= ebur128
->i3000
.histogram
[i
].loudness
;
807 /* get higher loudness to consider */
809 nb_pow
= LRA_HIGHER_PRC
* nb_powers
* 0.01 + 0.5;
810 for (i
= HIST_SIZE
- 1; i
>= 0; i
--) {
811 n
-= FFMIN(n
, ebur128
->i3000
.histogram
[i
].count
);
813 ebur128
->lra_high
= ebur128
->i3000
.histogram
[i
].loudness
;
818 // XXX: show low & high on the graph?
819 ebur128
->loudness_range
= ebur128
->lra_high
- ebur128
->lra_low
;
823 /* dual-mono correction */
824 if (nb_channels
== 1 && ebur128
->dual_mono
) {
825 loudness_400
-= ebur128
->pan_law
;
826 loudness_3000
-= ebur128
->pan_law
;
829 #define LOG_FMT "TARGET:%d LUFS M:%6.1f S:%6.1f I:%6.1f %s LRA:%6.1f LU"
831 /* push one video frame */
832 if (ebur128
->do_video
) {
837 int y_loudness_lu_graph
, y_loudness_lu_gauge
;
839 if (ebur128
->gauge_type
== GAUGE_TYPE_MOMENTARY
) {
840 gauge_value
= loudness_400
- ebur128
->target
;
842 gauge_value
= loudness_3000
- ebur128
->target
;
845 y_loudness_lu_graph
= lu_to_y(ebur128
, loudness_3000
- ebur128
->target
);
846 y_loudness_lu_gauge
= lu_to_y(ebur128
, gauge_value
);
848 ret
= ff_inlink_make_frame_writable(outlink
, &ebur128
->outpicref
);
850 av_frame_free(&insamples
);
851 ebur128
->insamples
= NULL
;
854 pic
= ebur128
->outpicref
;
855 /* draw the graph using the short-term loudness */
856 p
= pic
->data
[0] + ebur128
->graph
.y
*pic
->linesize
[0] + ebur128
->graph
.x
*3;
857 for (y
= 0; y
< ebur128
->graph
.h
; y
++) {
858 const uint8_t *c
= get_graph_color(ebur128
, y_loudness_lu_graph
, y
);
860 memmove(p
, p
+ 3, (ebur128
->graph
.w
- 1) * 3);
861 memcpy(p
+ (ebur128
->graph
.w
- 1) * 3, c
, 3);
862 p
+= pic
->linesize
[0];
865 /* draw the gauge using either momentary or short-term loudness */
866 p
= pic
->data
[0] + ebur128
->gauge
.y
*pic
->linesize
[0] + ebur128
->gauge
.x
*3;
867 for (y
= 0; y
< ebur128
->gauge
.h
; y
++) {
868 const uint8_t *c
= get_graph_color(ebur128
, y_loudness_lu_gauge
, y
);
870 for (x
= 0; x
< ebur128
->gauge
.w
; x
++)
871 memcpy(p
+ x
*3, c
, 3);
872 p
+= pic
->linesize
[0];
875 /* draw textual info */
876 if (ebur128
->scale
== SCALE_TYPE_ABSOLUTE
) {
877 drawtext(pic
, PAD
, PAD
- PAD
/2, FONT16
, font_colors
,
878 LOG_FMT
" ", // padding to erase trailing characters
879 ebur128
->target
, loudness_400
, loudness_3000
,
880 ebur128
->integrated_loudness
, "LUFS", ebur128
->loudness_range
);
882 drawtext(pic
, PAD
, PAD
- PAD
/2, FONT16
, font_colors
,
883 LOG_FMT
" ", // padding to erase trailing characters
884 ebur128
->target
, loudness_400
-ebur128
->target
, loudness_3000
-ebur128
->target
,
885 ebur128
->integrated_loudness
-ebur128
->target
, "LU", ebur128
->loudness_range
);
888 /* set pts and push frame */
889 pic
->pts
= av_rescale_q(pts
, inlink
->time_base
, outlink
->time_base
);
891 clone
= av_frame_clone(pic
);
893 return AVERROR(ENOMEM
);
894 ebur128
->idx_insample
= idx_insample
+ 1;
895 ff_filter_set_ready(ctx
, 100);
896 return ff_filter_frame(outlink
, clone
);
899 if (ebur128
->metadata
) { /* happens only once per filter_frame call */
901 #define META_PREFIX "lavfi.r128."
903 #define SET_META(name, var) do { \
904 snprintf(metabuf, sizeof(metabuf), "%.3f", var); \
905 av_dict_set(&insamples->metadata, name, metabuf, 0); \
908 #define SET_META_PEAK(name, ptype) do { \
909 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
910 double max_peak = 0.0; \
912 for (ch = 0; ch < nb_channels; ch++) { \
913 snprintf(key, sizeof(key), \
914 META_PREFIX AV_STRINGIFY(name) "_peaks_ch%d", ch); \
915 max_peak = fmax(max_peak, ebur128->name##_peaks[ch]); \
916 SET_META(key, ebur128->name##_peaks[ch]); \
918 snprintf(key, sizeof(key), \
919 META_PREFIX AV_STRINGIFY(name) "_peak"); \
920 SET_META(key, max_peak); \
924 SET_META(META_PREFIX
"M", loudness_400
);
925 SET_META(META_PREFIX
"S", loudness_3000
);
926 SET_META(META_PREFIX
"I", ebur128
->integrated_loudness
);
927 SET_META(META_PREFIX
"LRA", ebur128
->loudness_range
);
928 SET_META(META_PREFIX
"LRA.low", ebur128
->lra_low
);
929 SET_META(META_PREFIX
"LRA.high", ebur128
->lra_high
);
931 SET_META_PEAK(sample
, SAMPLES
);
932 SET_META_PEAK(true, TRUE
);
935 if (ebur128
->loglevel
!= AV_LOG_QUIET
) {
936 if (ebur128
->scale
== SCALE_TYPE_ABSOLUTE
) {
937 av_log(ctx
, ebur128
->loglevel
, "t: %-10s " LOG_FMT
,
938 av_ts2timestr(pts
, &outlink
->time_base
),
939 ebur128
->target
, loudness_400
, loudness_3000
,
940 ebur128
->integrated_loudness
, "LUFS", ebur128
->loudness_range
);
942 av_log(ctx
, ebur128
->loglevel
, "t: %-10s " LOG_FMT
,
943 av_ts2timestr(pts
, &outlink
->time_base
),
944 ebur128
->target
, loudness_400
-ebur128
->target
, loudness_3000
-ebur128
->target
,
945 ebur128
->integrated_loudness
-ebur128
->target
, "LU", ebur128
->loudness_range
);
948 #define PRINT_PEAKS(str, sp, ptype) do { \
949 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
950 av_log(ctx, ebur128->loglevel, " " str ":"); \
951 for (ch = 0; ch < nb_channels; ch++) \
952 av_log(ctx, ebur128->loglevel, " %5.1f", DBFS(sp[ch])); \
953 av_log(ctx, ebur128->loglevel, " dBFS"); \
957 PRINT_PEAKS("SPK", ebur128
->sample_peaks
, SAMPLES
);
958 PRINT_PEAKS("FTPK", ebur128
->true_peaks_per_frame
, TRUE
);
959 PRINT_PEAKS("TPK", ebur128
->true_peaks
, TRUE
);
960 av_log(ctx
, ebur128
->loglevel
, "\n");
965 ebur128
->idx_insample
= 0;
966 ebur128
->insamples
= NULL
;
968 return ff_filter_frame(ctx
->outputs
[ebur128
->do_video
], insamples
);
971 static int activate(AVFilterContext
*ctx
)
973 AVFilterLink
*inlink
= ctx
->inputs
[0];
974 EBUR128Context
*ebur128
= ctx
->priv
;
975 AVFilterLink
*voutlink
= ctx
->outputs
[0];
976 AVFilterLink
*outlink
= ctx
->outputs
[ebur128
->do_video
];
979 FF_FILTER_FORWARD_STATUS_BACK(outlink
, inlink
);
980 if (ebur128
->do_video
)
981 FF_FILTER_FORWARD_STATUS_BACK(voutlink
, inlink
);
983 if (!ebur128
->insamples
) {
986 if (ebur128
->nb_samples
> 0) {
987 ret
= ff_inlink_consume_samples(inlink
, ebur128
->nb_samples
, ebur128
->nb_samples
, &in
);
989 ret
= ff_inlink_consume_frame(inlink
, &in
);
994 ebur128
->insamples
= in
;
997 if (ebur128
->insamples
)
998 ret
= filter_frame(inlink
, ebur128
->insamples
);
1000 FF_FILTER_FORWARD_STATUS_ALL(inlink
, ctx
);
1001 FF_FILTER_FORWARD_WANTED(outlink
, inlink
);
1002 if (ebur128
->do_video
)
1003 FF_FILTER_FORWARD_WANTED(voutlink
, inlink
);
1008 static int query_formats(const AVFilterContext
*ctx
,
1009 AVFilterFormatsConfig
**cfg_in
,
1010 AVFilterFormatsConfig
**cfg_out
)
1012 const EBUR128Context
*ebur128
= ctx
->priv
;
1013 AVFilterFormats
*formats
;
1017 static const enum AVSampleFormat sample_fmts
[] = { AV_SAMPLE_FMT_DBL
, AV_SAMPLE_FMT_NONE
};
1018 static const enum AVPixelFormat pix_fmts
[] = { AV_PIX_FMT_RGB24
, AV_PIX_FMT_NONE
};
1020 /* set optional output video format */
1021 if (ebur128
->do_video
) {
1022 formats
= ff_make_format_list(pix_fmts
);
1023 if ((ret
= ff_formats_ref(formats
, &cfg_out
[0]->formats
)) < 0)
1028 /* set input and output audio formats
1029 * Note: ff_set_common_* functions are not used because they affect all the
1030 * links, and thus break the video format negotiation */
1031 formats
= ff_make_format_list(sample_fmts
);
1032 if ((ret
= ff_formats_ref(formats
, &cfg_in
[0]->formats
)) < 0 ||
1033 (ret
= ff_formats_ref(formats
, &cfg_out
[out_idx
]->formats
)) < 0)
1039 static av_cold
void uninit(AVFilterContext
*ctx
)
1041 EBUR128Context
*ebur128
= ctx
->priv
;
1043 /* dual-mono correction */
1044 if (ebur128
->nb_channels
== 1 && ebur128
->dual_mono
) {
1045 ebur128
->i400
.rel_threshold
-= ebur128
->pan_law
;
1046 ebur128
->i3000
.rel_threshold
-= ebur128
->pan_law
;
1047 ebur128
->lra_low
-= ebur128
->pan_law
;
1048 ebur128
->lra_high
-= ebur128
->pan_law
;
1051 if (ebur128
->nb_channels
> 0) {
1052 av_log(ctx
, AV_LOG_INFO
, "Summary:\n\n"
1053 " Integrated loudness:\n"
1055 " Threshold: %5.1f LUFS\n\n"
1056 " Loudness range:\n"
1058 " Threshold: %5.1f LUFS\n"
1059 " LRA low: %5.1f LUFS\n"
1060 " LRA high: %5.1f LUFS",
1061 ebur128
->integrated_loudness
, ebur128
->i400
.rel_threshold
,
1062 ebur128
->loudness_range
, ebur128
->i3000
.rel_threshold
,
1063 ebur128
->lra_low
, ebur128
->lra_high
);
1065 #define PRINT_PEAK_SUMMARY(str, value, ptype) do { \
1066 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
1067 av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \
1068 " Peak: %5.1f dBFS", value); \
1072 PRINT_PEAK_SUMMARY("Sample", ebur128
->sample_peak
, SAMPLES
);
1073 PRINT_PEAK_SUMMARY("True", ebur128
->true_peak
, TRUE
);
1074 av_log(ctx
, AV_LOG_INFO
, "\n");
1077 av_freep(&ebur128
->y_line_ref
);
1078 av_freep(&ebur128
->x
);
1079 av_freep(&ebur128
->y
);
1080 av_freep(&ebur128
->z
);
1081 av_freep(&ebur128
->ch_weighting
);
1082 av_freep(&ebur128
->true_peaks
);
1083 av_freep(&ebur128
->sample_peaks
);
1084 av_freep(&ebur128
->true_peaks_per_frame
);
1085 av_freep(&ebur128
->i400
.sum
);
1086 av_freep(&ebur128
->i3000
.sum
);
1087 av_freep(&ebur128
->i400
.histogram
);
1088 av_freep(&ebur128
->i3000
.histogram
);
1089 for (int i
= 0; i
< ebur128
->nb_channels
; i
++) {
1090 if (ebur128
->i400
.cache
)
1091 av_freep(&ebur128
->i400
.cache
[i
]);
1092 if (ebur128
->i3000
.cache
)
1093 av_freep(&ebur128
->i3000
.cache
[i
]);
1095 av_freep(&ebur128
->i400
.cache
);
1096 av_freep(&ebur128
->i3000
.cache
);
1097 av_frame_free(&ebur128
->outpicref
);
1098 #if CONFIG_SWRESAMPLE
1099 av_freep(&ebur128
->swr_buf
);
1100 swr_free(&ebur128
->swr_ctx
);
1104 static const AVFilterPad ebur128_inputs
[] = {
1107 .type
= AVMEDIA_TYPE_AUDIO
,
1108 .config_props
= config_audio_input
,
1112 const FFFilter ff_af_ebur128
= {
1113 .p
.name
= "ebur128",
1114 .p
.description
= NULL_IF_CONFIG_SMALL("EBU R128 scanner."),
1116 .p
.priv_class
= &ebur128_class
,
1117 .p
.flags
= AVFILTER_FLAG_DYNAMIC_OUTPUTS
,
1118 .priv_size
= sizeof(EBUR128Context
),
1121 .activate
= activate
,
1122 FILTER_INPUTS(ebur128_inputs
),
1123 FILTER_QUERY_FUNC2(query_formats
),