46 #define MAX_CHANNELS 63
49 #define PRE_B0 1.53512485958697
50 #define PRE_B1 -2.69169618940638
51 #define PRE_B2 1.19839281085285
52 #define PRE_A1 -1.69065929318241
53 #define PRE_A2 0.73248077421585
59 #define RLB_A1 -1.99004745483398
60 #define RLB_A2 0.99007225036621
63 #define ABS_UP_THRES 10
64 #define HIST_GRAIN 100
65 #define HIST_SIZE ((ABS_UP_THRES - ABS_THRES) * HIST_GRAIN + 1)
101 #if CONFIG_SWRESAMPLE
130 #define I400_BINS (48000 * 4 / 10)
131 #define I3000_BINS (48000 * 3)
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
161 {
"framelog",
"force frame logging level",
OFFSET(loglevel),
AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX,
A|
V|
F,
"level" },
170 {
"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 },
189 const int below0 = y > ebur128->
y_zero_lu;
190 const int reached = y >= v;
192 const int colorid = 4*line + 2*reached + below0;
198 v += 2 * ebur128->
meter;
228 for (i = 0; buf[i]; i++) {
232 for (char_y = 0; char_y < font_height; char_y++) {
233 for (mask = 0x80;
mask; mask >>= 1) {
234 if (font[buf[i] * font_height + char_y] & mask)
237 memcpy(p,
"\x00\x00\x00", 3);
250 for (i = 0; i <
len; i++) {
251 memcpy(p,
"\x00\xff\x00", 3);
265 if (ebur128->
w < 640 || ebur128->
h < 480) {
267 "minimum size is 640x480\n", ebur128->
w, ebur128->
h);
270 outlink->
w = ebur128->
w;
271 outlink->
h = ebur128->
h;
277 ebur128->
text.
y = 40;
278 ebur128->
text.
w = 3 * 8;
310 memset(outpicref->
data[0], 0, ebur128->
h * outpicref->
linesize[0]);
314 for (i = ebur128->
meter; i >= -ebur128->
meter * 2; i--) {
316 x =
PAD + (i < 10 && i > -10) * 8;
320 "%c%d", i < 0 ? '-' : i > 0 ?
'+' :
' ',
FFABS(i));
327 for (y = 0; y < ebur128->
graph.
h; y++) {
330 for (x = 0; x < ebur128->
graph.
w; x++)
331 memcpy(p + x*3, c, 3);
336 #define DRAW_RECT(r) do { \
337 drawline(outpicref, r.x, r.y - 1, r.w, 3); \
338 drawline(outpicref, r.x, r.y + r.h, r.w, 3); \
339 drawline(outpicref, r.x - 1, r.y, r.h, outpicref->linesize[0]); \
340 drawline(outpicref, r.x + r.w, r.y, r.h, outpicref->linesize[0]); \
373 #define BACK_MASK (AV_CH_BACK_LEFT |AV_CH_BACK_CENTER |AV_CH_BACK_RIGHT| \
374 AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_BACK_RIGHT| \
375 AV_CH_SIDE_LEFT |AV_CH_SIDE_RIGHT| \
376 AV_CH_SURROUND_DIRECT_LEFT |AV_CH_SURROUND_DIRECT_RIGHT)
404 #if CONFIG_SWRESAMPLE
408 ebur128->swr_buf =
av_malloc_array(nb_channels, 19200 *
sizeof(
double));
412 if (!ebur128->swr_buf || !ebur128->
true_peaks ||
439 #define ENERGY(loudness) (ff_exp10(((loudness) + 0.691) / 10.))
440 #define LOUDNESS(energy) (-0.691 + 10 * log10(energy))
441 #define DBFS(energy) (20 * log10(energy))
472 "True-peak mode requires libswresample to be performed\n");
514 #define HIST_POS(power) (int)(((power) - ABS_THRES) * HIST_GRAIN)
522 double relative_threshold;
533 if (!relative_threshold)
534 relative_threshold = 1e-12;
538 return gate_hist_pos;
543 int i, ch, idx_insample;
548 const double *samples = (
double *)insamples->
data[0];
551 #
if CONFIG_SWRESAMPLE
553 const double *swr_samples = ebur128->swr_buf;
560 for (idx_insample = 0; idx_insample < ret; idx_insample++) {
571 for (idx_insample = 0; idx_insample < nb_samples; idx_insample++) {
575 #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \
576 ebur128->i##time.cache_pos++; \
577 if (ebur128->i##time.cache_pos == I##time##_BINS) { \
578 ebur128->i##time.filled = 1; \
579 ebur128->i##time.cache_pos = 0; \
592 ebur128->
x[ch * 3] = *samples++;
598 #define FILTER(Y, X, name) do { \
599 double *dst = ebur128->Y + ch*3; \
600 double *src = ebur128->X + ch*3; \
603 dst[0] = src[0]*name##_B0 + src[1]*name##_B1 + src[2]*name##_B2 \
604 - dst[1]*name##_A1 - dst[2]*name##_A2; \
609 ebur128->
x[ch * 3 + 2] = ebur128->
x[ch * 3 + 1];
610 ebur128->
x[ch * 3 + 1] = ebur128->
x[ch * 3 ];
613 bin = ebur128->
z[ch * 3] * ebur128->
z[ch * 3];
621 ebur128->
i400.
cache [ch][bin_id_400 ] = bin;
629 double loudness_400, loudness_3000;
630 double power_400 = 1e-12, power_3000 = 1e-12;
632 const int64_t
pts = insamples->
pts +
638 #define COMPUTE_LOUDNESS(m, time) do { \
639 if (ebur128->i##time.filled) { \
641 for (ch = 0; ch < nb_channels; ch++) \
642 power_##time += ebur128->ch_weighting[ch] * ebur128->i##time.sum[ch]; \
643 power_##time /= I##time##_BINS; \
645 loudness_##time = LOUDNESS(power_##time); \
652 #define I_GATE_THRES -10 // initially defined to -8 LU in the first EBU standard
655 double integrated_sum = 0;
656 int nb_integrated = 0;
662 for (i = gate_hist_pos; i <
HIST_SIZE; i++) {
664 nb_integrated += nb_v;
670 if (nb_channels == 1 && ebur128->
dual_mono) {
677 #define LRA_GATE_THRES -20
678 #define LRA_LOWER_PRC 10
679 #define LRA_HIGHER_PRC 95
688 for (i = gate_hist_pos; i <
HIST_SIZE; i++)
696 for (i = gate_hist_pos; i <
HIST_SIZE; i++) {
707 for (i = HIST_SIZE - 1; i >= 0; i--) {
721 if (nb_channels == 1 && ebur128->
dual_mono) {
722 loudness_400 -= ebur128->
pan_law;
723 loudness_3000 -= ebur128->
pan_law;
726 #define LOG_FMT "M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU"
733 const int y_loudness_lu_graph =
lu_to_y(ebur128, loudness_3000 + 23);
734 const int y_loudness_lu_gauge =
lu_to_y(ebur128, loudness_400 + 23);
737 p = pic->data[0] + ebur128->
graph.
y*pic->linesize[0] + ebur128->
graph.
x*3;
738 for (y = 0; y < ebur128->
graph.
h; y++) {
741 memmove(p, p + 3, (ebur128->
graph.
w - 1) * 3);
742 memcpy(p + (ebur128->
graph.
w - 1) * 3, c, 3);
743 p += pic->linesize[0];
747 p = pic->data[0] + ebur128->
gauge.
y*pic->linesize[0] + ebur128->
gauge.
x*3;
748 for (y = 0; y < ebur128->
gauge.
h; y++) {
751 for (x = 0; x < ebur128->
gauge.
w; x++)
752 memcpy(p + x*3, c, 3);
753 p += pic->linesize[0];
759 loudness_400, loudness_3000,
771 #define META_PREFIX "lavfi.r128."
773 #define SET_META(name, var) do { \
774 snprintf(metabuf, sizeof(metabuf), "%.3f", var); \
775 av_dict_set(&insamples->metadata, name, metabuf, 0); \
778 #define SET_META_PEAK(name, ptype) do { \
779 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
781 for (ch = 0; ch < nb_channels; ch++) { \
782 snprintf(key, sizeof(key), \
783 META_PREFIX AV_STRINGIFY(name) "_peaks_ch%d", ch); \
784 SET_META(key, ebur128->name##_peaks[ch]); \
802 loudness_400, loudness_3000,
805 #define PRINT_PEAKS(str, sp, ptype) do { \
806 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
807 av_log(ctx, ebur128->loglevel, " " str ":"); \
808 for (ch = 0; ch < nb_channels; ch++) \
809 av_log(ctx, ebur128->loglevel, " %5.1f", DBFS(sp[ch])); \
810 av_log(ctx, ebur128->loglevel, " dBFS"); \
834 static const int input_srate[] = {48000, -1};
880 " Integrated loudness:\n"
882 " Threshold: %5.1f LUFS\n\n"
885 " Threshold: %5.1f LUFS\n"
886 " LRA low: %5.1f LUFS\n"
887 " LRA high: %5.1f LUFS",
892 #define PRINT_PEAK_SUMMARY(str, sp, ptype) do { \
896 if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \
897 for (ch = 0; ch < ebur128->nb_channels; ch++) \
898 maxpeak = FFMAX(maxpeak, sp[ch]); \
899 av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \
900 " Peak: %5.1f dBFS", \
923 #if CONFIG_SWRESAMPLE
948 .priv_class = &ebur128_class,
static struct hist_entry * get_histogram(void)
This structure describes decoded (raw) audio or video data.
int scale_range
the range of LU values according to the meter
static int query_formats(AVFilterContext *ctx)
double * true_peaks_per_frame
true peaks in a frame per channel
struct hist_entry * histogram
histogram of the powers, used to compute LRA and I
static int config_video_output(AVFilterLink *outlink)
int sample_count
sample count used for refresh frequency, reset at refresh
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
int y_zero_lu
the y value (pixel position) for 0 LU
int max_samples
Maximum number of samples to filter at once.
static int config_audio_output(AVFilterLink *outlink)
int h
agreed upon image height
static int lu_to_y(const EBUR128Context *ebur128, double v)
#define COMPUTE_LOUDNESS(m, time)
static av_cold int init(AVFilterContext *ctx)
int cache_pos
focus on the last added bin in the cache array
#define SET_META_PEAK(name, ptype)
#define AV_CH_LOW_FREQUENCY_2
static enum AVSampleFormat formats[]
const uint8_t avpriv_vga16_font[4096]
int do_video
1 if video output enabled, 0 otherwise
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
static const AVOption ebur128_options[]
struct AVFilterChannelLayouts * in_channel_layouts
#define PRINT_PEAKS(str, sp, ptype)
int nb_channels
number of channels in the input
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
AVFILTER_DEFINE_CLASS(ebur128)
int metadata
whether or not to inject loudness results in frames
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define HIST_GRAIN
defines histogram precision
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
AVFilterPad * output_pads
array of output pads
av_cold struct SwrContext * swr_alloc(void)
Allocate SwrContext.
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)
double sum_kept_powers
sum of the powers (weighted sums) above absolute threshold
timestamp utils, mostly useful for debugging/logging purposes
static void drawline(AVFrame *pic, int x, int y, int len, int step)
double * cache[MAX_CHANNELS]
window of filtered samples (N ms)
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
true peaks per channel
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
static const uint8_t font_colors[]
#define AV_CH_LOW_FREQUENCY
int meter
select a EBU mode between +9 and +18
#define AV_LOG_VERBOSE
Detailed information.
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
A histogram is an array of HIST_SIZE hist_entry storing all the energies recorded (with an accuracy o...
AVFrame * outpicref
output picture reference, updated regularly
A filter pad used for either input or output.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
A link between two filters.
libswresample public header
double * sample_peaks
sample peaks per channel
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const uint8_t avpriv_cga_font[2048]
int min_samples
Minimum number of samples to filter at once.
int sample_rate
samples per second
int count
how many times the corresponding value occurred
static const uint16_t mask[17]
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define av_ts2timestr(ts, tb)
Convenience macro, the return value should be used only directly in function arguments but never stan...
unsigned nb_outputs
number of output pads
The libswresample context.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link...
simple assert() macros that are a bit more flexible than ISO C assert().
struct AVFilterChannelLayouts * out_channel_layouts
AVFilterFormats * in_formats
Lists of formats and channel layouts supported by the input and output filters respectively.
#define MOVE_TO_NEXT_CACHED_ENTRY(time)
struct integrator i400
400ms integrator, used for Momentary loudness (M), and Integrated loudness (I)
int w
agreed upon image width
static av_cold void uninit(AVFilterContext *ctx)
char * av_asprintf(const char *fmt,...)
int * y_line_ref
y reference values for drawing the LU lines in the graph and the gauge
struct rect graph
rectangle for the main graph in the center
audio channel layout utility functions
double loudness
L = -0.691 + 10 * log10(E)
double rel_threshold
relative threshold
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
AVFilterContext * src
source filter
int partial_buf_size
Size of the partial buffer to allocate.
double loudness_range
loudness range in LU (LRA)
static const AVFilterPad outputs[]
AVFilterFormats * out_samplerates
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
int format
agreed upon media format
A list of supported channel layouts.
#define AV_LOG_INFO
Standard information.
static const AVFilterPad inputs[]
AVFilterFormats * in_samplerates
Lists of channel layouts and sample rates used for automatic negotiation.
AVSampleFormat
Audio sample formats.
char * av_strdup(const char *s)
Duplicate the string s.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
#define ABS_THRES
silence gate: we discard anything below this absolute (LUFS) threshold
av_cold void swr_free(SwrContext **ss)
Free the given SwrContext and set the pointer to NULL.
int nb_kept_powers
number of sum above absolute threshold
Describe the class of an AVClass context structure.
rational number numerator/denominator
const char * name
Filter name.
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
offset must point to two consecutive integers
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, const uint8_t *in_arg[SWR_CH_MAX], int in_count)
AVFilterLink ** outputs
array of pointers to output links
enum MovChannelLayoutTag * layouts
static enum AVPixelFormat pix_fmts[]
void * av_calloc(size_t nmemb, size_t size)
Allocate a block of nmemb * size bytes with alignment suitable for all memory accesses (including vec...
static int64_t pts
Global timestamp for the audio frames.
int dual_mono
whether or not to treat single channel input files as dual-mono
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
struct rect text
rectangle for the LU legend on the left
internal math functions header
static const AVFilterPad ebur128_inputs[]
int h
size of the video output
#define PRINT_PEAK_SUMMARY(str, sp, ptype)
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
Get the channel with the given index in channel_layout.
struct rect gauge
rectangle for the gauge on the right
uint64_t channel_layout
channel layout of current buffer (see libavutil/channel_layout.h)
static int config_audio_input(AVFilterLink *inlink)
static int gate_update(struct integrator *integ, double power, double loudness, int gate_thres)
int loglevel
log level for frame logging
double x[MAX_CHANNELS *3]
3 input samples cache for each channel
#define FILTER(Y, X, name)
double lra_high
low and high LRA values
AVFilterContext * dst
dest filter
static enum AVSampleFormat sample_fmts[]
double sum[MAX_CHANNELS]
sum of the last N ms filtered samples (cache content)
double z[MAX_CHANNELS *3]
3 RLB-filter samples cache for each channel
#define SET_META(name, var)
int peak_mode
enabled peak modes
#define av_malloc_array(a, b)
double * ch_weighting
channel weighting mapping
double pan_law
pan law value used to calulate dual-mono measurements
int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags)
static int ff_insert_outpad(AVFilterContext *f, unsigned index, AVFilterPad *p)
Insert a new output pad for the filter.
AVPixelFormat
Pixel format.
int nb_samples
number of audio samples (per channel) described by this frame
static const uint8_t graph_colors[]
CGA/EGA/VGA ROM font data.
AVFilterFormats * out_formats
av_cold int swr_init(struct SwrContext *s)
Initialize context after user parameters have been set.
double energy
E = 10^((L + 0.691) / 10)
int filled
1 if the cache is completely filled, 0 otherwise
static const uint8_t * get_graph_color(const EBUR128Context *ebur128, int v, int y)