49#define ABS_UP_THRES 10
51#define HIST_SIZE ((ABS_UP_THRES - ABS_THRES) * HIST_GRAIN + 1)
153#define OFFSET(x) offsetof(EBUR128Context, x)
154#define A AV_OPT_FLAG_AUDIO_PARAM
155#define V AV_OPT_FLAG_VIDEO_PARAM
156#define F AV_OPT_FLAG_FILTERING_PARAM
157#define X AV_OPT_FLAG_EXPORT
158#define R AV_OPT_FLAG_READONLY
163 {
"framelog",
"force frame logging level",
OFFSET(loglevel),
AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX,
A|
V|
F, .unit =
"level" },
173 {
"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 },
174 {
"target",
"set a specific target level in LUFS (-23 to 0)",
OFFSET(target),
AV_OPT_TYPE_INT, {.i64 = -23}, -23, 0,
V|
F },
185 {
"integrated",
"integrated loudness (LUFS)",
OFFSET(integrated_loudness),
AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX,
A|
F|
X|
R },
217 const int above_opt_max = y > ebur128->
y_opt_max;
218 const int below_opt_min = y < ebur128->
y_opt_min;
219 const int reached = y >= v;
221 const int colorid = 8*below_opt_min+ 4*
line + 2*reached + above_opt_max;
227 v += 2 * ebur128->
meter;
257 for (
i = 0; buf[
i];
i++) {
259 uint8_t *p = pic->
data[0] + y*pic->
linesize[0] + (x +
i*8)*3;
261 for (char_y = 0; char_y < font_height; char_y++) {
263 if (font[buf[
i] * font_height + char_y] &
mask)
266 memcpy(p,
"\x00\x00\x00", 3);
279 for (
i = 0;
i <
len;
i++) {
280 memcpy(p,
"\x00\xff\x00", 3);
295 if (ebur128->
w < 640 || ebur128->
h < 480) {
297 "minimum size is 640x480\n", ebur128->
w, ebur128->
h);
300 outlink->
w = ebur128->
w;
301 outlink->
h = ebur128->
h;
310 ebur128->
text.
y = 40;
311 ebur128->
text.
w = 3 * 8;
343 for (
int y = 0; y < ebur128->
h; y++)
344 memset(outpicref->
data[0] + y * outpicref->
linesize[0], 0, ebur128->
w * 3);
354 "%c%d",
i < 0 ?
'-' :
i > 0 ?
'+' :
' ',
FFABS(
i));
363 for (y = 0; y < ebur128->
graph.
h; y++) {
366 for (x = 0; x < ebur128->
graph.
w; x++)
367 memcpy(p + x*3,
c, 3);
372#define DRAW_RECT(r) do { \
373 drawline(outpicref, r.x, r.y - 1, r.w, 3); \
374 drawline(outpicref, r.x, r.y + r.h, r.w, 3); \
375 drawline(outpicref, r.x - 1, r.y, r.h, outpicref->linesize[0]); \
376 drawline(outpicref, r.x + r.w, r.y, r.h, outpicref->linesize[0]); \
392 double f0 = 1681.974450955533;
393 double G = 3.999843853973347;
394 double Q = 0.7071752369554196;
397 double Vh = pow(10.0,
G / 20.0);
398 double Vb = pow(Vh, 0.4996667741545416);
400 double a0 = 1.0 +
K /
Q +
K *
K;
408 f0 = 38.13547087602444;
409 Q = 0.5003270373238773;
415 ebur128->
dsp.
rlb.
a1 = 2.0 * (
K *
K - 1.0) / (1.0 +
K /
Q +
K *
K);
437#define WEIGHT_1_41_MASK (AV_CH_BACK_LEFT |AV_CH_BACK_CENTER | \
438 AV_CH_BACK_RIGHT |AV_CH_SIDE_LEFT | \
439 AV_CH_SIDE_RIGHT |AV_CH_SURROUND_DIRECT_LEFT | \
440 AV_CH_SURROUND_DIRECT_RIGHT)
449#define I400_BINS(x) ((x) * 2 / 5)
450#define I3000_BINS(x) ((x) * 3)
457 size_t i400_count, i3000_count;
469 for (
i = 0;
i < nb_channels;
i++) {
485 ebur128->swr_buf =
av_malloc_array(nb_channels, 19200 *
sizeof(
double));
489 if (!ebur128->swr_buf || !ebur128->
true_peaks ||
513#if ARCH_X86 && HAVE_X86ASM
519#define ENERGY(loudness) (ff_exp10(((loudness) + 0.691) / 10.))
520#define LOUDNESS(energy) (-0.691 + 10 * log10(energy))
521#define DBFS(energy) (20 * log10(energy))
554 "True-peak mode requires libswresample to be performed\n");
582 .name = ebur128->
do_video ?
"out1" :
"out0",
598#define HIST_POS(power) (int)(((power) - ABS_THRES) * HIST_GRAIN)
606 double relative_threshold;
617 if (!relative_threshold)
618 relative_threshold = 1e-12;
622 return gate_hist_pos;
626 const double *restrict samples,
627 double *restrict cache_400,
628 double *restrict cache_3000,
629 double *restrict sum_400,
630 double *restrict sum_3000,
631 const int nb_channels)
636 for (
int ch = 0; ch < nb_channels; ch++) {
638#define FILTER(DST, SRC, FILT) do { \
639 const double tmp = DST[0] = FILT.b0 * SRC + DST[1]; \
640 DST[1] = FILT.b1 * SRC + DST[2] - FILT.a1 * tmp; \
641 DST[2] = FILT.b2 * SRC - FILT.a2 * tmp; \
644 const double x = samples[ch];
645 double *restrict y = &dsp->
y[3 * ch];
646 double *restrict z = &dsp->
z[3 * ch];
654 const double bin = *z * *z;
655 sum_400 [ch] += bin - cache_400[ch];
656 sum_3000[ch] += bin - cache_3000[ch];
657 cache_400[ch] = cache_3000[ch] = bin;
662 const double *samples,
const int nb_samples)
664 double maxpeak = 0.0;
665 for (
int ch = 0; ch < nb_channels; ch++) {
666 double ch_peak = ch_peaks[ch];
667 for (
int i = 0;
i < nb_samples;
i++) {
668 const double sample =
fabs(samples[
i * nb_channels + ch]);
671 maxpeak =
FFMAX(maxpeak, ch_peak);
672 ch_peaks[ch] = ch_peak;
686 const double *samples = (
double *)insamples->
data[0];
691 const double *swr_samples = ebur128->swr_buf;
692 int ret =
swr_convert(ebur128->swr_ctx, (uint8_t**)&ebur128->swr_buf, 19200,
693 (
const uint8_t **)insamples->
data, nb_samples);
703 for (
int ch = 0; ch < nb_channels; ch++) {
715 samples, nb_samples);
719 for (
int idx_insample = ebur128->
idx_insample; idx_insample < nb_samples; idx_insample++) {
734 &ebur128->
i400.
cache[bin_id_400 * nb_channels],
735 &ebur128->
i3000.
cache[bin_id_3000 * nb_channels],
743 double loudness_400, loudness_3000;
744 double power_400 = 1e-12, power_3000 = 1e-12;
752#define COMPUTE_LOUDNESS(m, time) do { \
753 if (ebur128->i##time.filled) { \
755 for (int ch = 0; ch < nb_channels; ch++) \
756 power_##time += ebur128->ch_weighting[ch] * ebur128->i##time.sum[ch]; \
757 power_##time /= I##time##_BINS(inlink->sample_rate); \
759 loudness_##time = LOUDNESS(power_##time); \
766#define I_GATE_THRES -10
769 double integrated_sum = 0.0;
770 uint64_t nb_integrated = 0;
778 nb_integrated += nb_v;
784 if (nb_channels == 1 && ebur128->
dual_mono) {
791#define LRA_GATE_THRES -20
792#define LRA_LOWER_PRC 10
793#define LRA_HIGHER_PRC 95
798 uint64_t nb_powers = 0;
835 if (nb_channels == 1 && ebur128->
dual_mono) {
836 loudness_400 -= ebur128->
pan_law;
837 loudness_3000 -= ebur128->
pan_law;
840#define LOG_FMT "TARGET:%d LUFS M:%6.1f S:%6.1f I:%6.1f %s LRA:%6.1f LU"
848 int y_loudness_lu_graph, y_loudness_lu_gauge;
851 gauge_value = loudness_400 - ebur128->
target;
853 gauge_value = loudness_3000 - ebur128->
target;
856 y_loudness_lu_graph =
lu_to_y(ebur128, loudness_3000 - ebur128->
target);
857 y_loudness_lu_gauge =
lu_to_y(ebur128, gauge_value);
868 for (y = 0; y < ebur128->
graph.
h; y++) {
871 memmove(p, p + 3, (ebur128->
graph.
w - 1) * 3);
872 memcpy(p + (ebur128->
graph.
w - 1) * 3,
c, 3);
878 for (y = 0; y < ebur128->
gauge.
h; y++) {
881 for (x = 0; x < ebur128->
gauge.
w; x++)
882 memcpy(p + x*3,
c, 3);
890 ebur128->
target, loudness_400, loudness_3000,
912#define META_PREFIX "lavfi.r128."
914#define SET_META(name, var) do { \
915 snprintf(metabuf, sizeof(metabuf), "%.3f", var); \
916 av_dict_set(&insamples->metadata, name, metabuf, 0); \
919#define SET_META_PEAK(name, ptype) do { \
920 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
921 double max_peak = 0.0; \
923 for (int ch = 0; ch < nb_channels; ch++) { \
924 snprintf(key, sizeof(key), \
925 META_PREFIX AV_STRINGIFY(name) "_peaks_ch%d", ch); \
926 max_peak = fmax(max_peak, ebur128->name##_peaks[ch]); \
927 SET_META(key, ebur128->name##_peaks[ch]); \
929 snprintf(key, sizeof(key), \
930 META_PREFIX AV_STRINGIFY(name) "_peak"); \
931 SET_META(key, max_peak); \
950 ebur128->
target, loudness_400, loudness_3000,
959#define PRINT_PEAKS(str, sp, ptype) do { \
960 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
961 av_log(ctx, ebur128->loglevel, " " str ":"); \
962 for (int ch = 0; ch < nb_channels; ch++) \
963 av_log(ctx, ebur128->loglevel, " %5.1f", DBFS(sp[ch])); \
964 av_log(ctx, ebur128->loglevel, " dBFS"); \
1064 " Integrated loudness:\n"
1066 " Threshold: %5.1f LUFS\n\n"
1067 " Loudness range:\n"
1069 " Threshold: %5.1f LUFS\n"
1070 " LRA low: %5.1f LUFS\n"
1071 " LRA high: %5.1f LUFS",
1076#define PRINT_PEAK_SUMMARY(str, value, ptype) do { \
1077 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
1078 av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \
1079 " Peak: %5.1f dBFS", value); \
1102#if CONFIG_SWRESAMPLE
1117 .p.name =
"ebur128",
1120 .p.priv_class = &ebur128_class,
static enum AVSampleFormat sample_fmts[]
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
const FFFilter ff_af_ebur128
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
static int config_video_output(AVFilterLink *outlink)
int ff_append_outpad(AVFilterContext *f, AVFilterPad *p)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe)
Make sure a frame is writable.
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Main libavfilter public API header.
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define i(width, name, range_min, range_max)
Public libavutil channel layout APIs header.
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static __device__ float fabs(float a)
int(* init)(AVBSFContext *ctx)
@ PEAK_MODE_SAMPLES_PEAKS
static int gate_update(struct integrator *integ, double power, double loudness, int gate_thres)
void ff_ebur128_filter_channels_c(const EBUR128DSPContext *dsp, const double *restrict samples, double *restrict cache_400, double *restrict cache_3000, double *restrict sum_400, double *restrict sum_3000, const int nb_channels)
static void drawtext(AVFrame *pic, int x, int y, int ftid, const uint8_t *color, const char *fmt,...)
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
static const uint8_t graph_colors[]
#define SET_META_PEAK(name, ptype)
static void drawline(AVFrame *pic, int x, int y, int len, int step)
static const uint8_t font_colors[]
static const AVFilterPad ebur128_inputs[]
static int config_audio_output(AVFilterLink *outlink)
static struct hist_entry * get_histogram(void)
#define PRINT_PEAK_SUMMARY(str, value, ptype)
#define FILTER(DST, SRC, FILT)
static const AVOption ebur128_options[]
static const uint8_t * get_graph_color(const EBUR128Context *ebur128, int v, int y)
#define COMPUTE_LOUDNESS(m, time)
#define SET_META(name, var)
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static int activate(AVFilterContext *ctx)
#define HIST_GRAIN
defines histogram precision
static av_cold void uninit(AVFilterContext *ctx)
static int config_audio_input(AVFilterLink *inlink)
double ff_ebur128_find_peak_c(double *restrict ch_peaks, const int nb_channels, const double *samples, const int nb_samples)
#define ABS_THRES
silence gate: we discard anything below this absolute (LUFS) threshold
static int config_video_output(AVFilterLink *outlink)
static int lu_to_y(const EBUR128Context *ebur128, double v)
#define PRINT_PEAKS(str, sp, ptype)
void ff_ebur128_init_x86(EBUR128DSPContext *dsp, int nb_channels)
internal math functions header
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
@ AV_CHAN_LOW_FREQUENCY_2
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
#define AV_LOG_QUIET
Print no output.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static AVRational av_make_q(int num, int den)
Create an AVRational.
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
int av_size_mult(size_t a, size_t b, size_t *r)
Multiply two size_t values checking for overflow.
AVSampleFormat
Audio sample formats.
@ AV_SAMPLE_FMT_DBL
double
av_cold struct SwrContext * swr_alloc(void)
Allocate SwrContext.
av_cold void swr_free(SwrContext **ss)
Free the given SwrContext and set the pointer to NULL.
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *const *out_arg, int out_count, const uint8_t *const *in_arg, int in_count)
Convert audio.
av_cold int swr_init(struct SwrContext *s)
Initialize context after user parameters have been set.
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *channel_layout, int search_flags)
int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags)
static void scale(int *out, const int *in, const int w, const int h, const int shift)
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
#define FF_FILTER_FORWARD_STATUS_ALL(inlink, filter)
Acknowledge the status on an input link and forward it to an output link.
#define FILTER_INPUTS(array)
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
static FilterLink * ff_filter_link(AVFilterLink *link)
#define AVFILTER_DEFINE_CLASS(fname)
#define FILTER_QUERY_FUNC2(func)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static enum AVPixelFormat pix_fmts[]
static const uint16_t mask[17]
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
static float power(float r, float g, float b, float max)
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
int sample_rate
samples per second
AVChannelLayout ch_layout
channel layout of current buffer (see libavutil/channel_layout.h)
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
AVFilterContext * dst
dest filter
int format
agreed upon media format
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
int nb_samples
number of audio samples (per channel) described by this frame
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
int64_t duration
Duration of the frame, in the same units as pts.
Rational number (pair of numerator and denominator).
int gauge_type
whether gauge shows momentary or short
int y_opt_max
the y value (pixel position) for 1 LU
int idx_insample
current sample position of processed samples in single input frame
double sample_peak
global sample peak
double true_peak
global true peak
int peak_mode
enabled peak modes
AVFrame * outpicref
output picture reference, updated regularly
int meter
select a EBU mode between +9 and +18
int nb_samples
number of samples to consume per single input frame
int h
size of the video output
struct rect gauge
rectangle for the gauge on the right
double lra_high
low and high LRA values
double pan_law
pan law value used to calculate dual-mono measurements
struct integrator i3000
3s integrator, used for Short term loudness (S), and Loudness Range (LRA)
double integrated_loudness
integrated loudness in LUFS (I)
double * true_peaks_per_frame
true peaks in a frame per channel
int loglevel
log level for frame logging
int y_zero_lu
the y value (pixel position) for 0 LU
int metadata
whether or not to inject loudness results in frames
int scale_range
the range of LU values according to the meter
AVFrame * insamples
input samples reference, updated regularly
int do_video
1 if video output enabled, 0 otherwise
int nb_channels
number of channels in the input
double loudness_range
loudness range in LU (LRA)
int dual_mono
whether or not to treat single channel input files as dual-mono
int scale
display scale type of statistics
struct integrator i400
400ms integrator, used for Momentary loudness (M), and Integrated loudness (I)
int y_opt_min
the y value (pixel position) for -1 LU
double * ch_weighting
channel weighting mapping
double * true_peaks
true peaks per channel
struct rect text
rectangle for the LU legend on the left
int * y_line_ref
y reference values for drawing the LU lines in the graph and the gauge
int sample_count
sample count used for refresh frequency, reset at refresh
struct rect graph
rectangle for the main graph in the center
double * sample_peaks
sample peaks per channel
int target
target level in LUFS used to set relative zero LU in visualization
double(* find_peak)(double *ch_peaks, int nb_channels, const double *samples, int nb_samples)
void(* filter_channels)(const struct EBUR128DSPContext *dsp, const double *samples, double *cache_400, double *cache_3000, double *sum_400, double *sum_3000, int nb_channels)
Link properties exposed to filter code, but not external callers.
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable.
The libswresample context.
A histogram is an array of HIST_SIZE hist_entry storing all the energies recorded (with an accuracy o...
double energy
E = 10^((L + 0.691) / 10)
unsigned count
how many times the corresponding value occurred
double loudness
L = -0.691 + 10 * log10(E)
double rel_threshold
relative threshold
struct hist_entry * histogram
histogram of the powers, used to compute LRA and I
double * cache
window of filtered samples (N ms)
double * sum
sum of the last N ms filtered samples (cache content)
int nb_kept_powers
number of sum above absolute threshold
int filled
1 if the cache is completely filled, 0 otherwise
double sum_kept_powers
sum of the powers (weighted sums) above absolute threshold
int cache_pos
focus on the last added bin in the cache array
libswresample public header
#define av_malloc_array(a, b)
static AVFormatContext * ctx
timestamp utils, mostly useful for debugging/logging purposes
#define av_ts2timestr(ts, tb)
Convenience macro, the return value should be used only directly in function arguments but never stan...
static double a0(void *priv, double x, double y)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
const uint8_t * avpriv_vga16_font_get(void)
const uint8_t * avpriv_cga_font_get(void)
CGA/EGA/VGA ROM font data.