Commit d5873909 authored by Daniel Molkentin's avatar Daniel Molkentin Committed by Paul B Mahol

libavfilter/ebur128: add gauge option

Allow to show short-term instead of momentary in gauge. Useful for monitoring
whilst live mixing.
Signed-off-by: 's avatarDaniel Molkentin <daniel@molkentin.de>
Signed-off-by: 's avatarConrad Zelck <c.zelck@imail.de>
parent 1cee8f03
...@@ -19281,7 +19281,8 @@ time graph to observe the loudness evolution. The graphic contains the logged ...@@ -19281,7 +19281,8 @@ time graph to observe the loudness evolution. The graphic contains the logged
message mentioned above, so it is not printed anymore when this option is set, message mentioned above, so it is not printed anymore when this option is set,
unless the verbose logging is set. The main graphing area contains the unless the verbose logging is set. The main graphing area contains the
short-term loudness (3 seconds of analysis), and the gauge on the right is for short-term loudness (3 seconds of analysis), and the gauge on the right is for
the momentary loudness (400 milliseconds). the momentary loudness (400 milliseconds), but can optionally be configured
to instead display short-term loudness (see @var{gauge}).
More information about the Loudness Recommendation EBU R128 on More information about the Loudness Recommendation EBU R128 on
@url{http://tech.ebu.ch/loudness}. @url{http://tech.ebu.ch/loudness}.
...@@ -19364,6 +19365,12 @@ Set a specific target level (in LUFS) used as relative zero in the visualization ...@@ -19364,6 +19365,12 @@ Set a specific target level (in LUFS) used as relative zero in the visualization
This parameter is optional and has a default value of -23LUFS as specified This parameter is optional and has a default value of -23LUFS as specified
by EBU R128. However, material published online may prefer a level of -16LUFS by EBU R128. However, material published online may prefer a level of -16LUFS
(e.g. for use with podcasts or video platforms). (e.g. for use with podcasts or video platforms).
@item gauge
Set the value displayed by the gauge. Valid values are @code{momentary} and s
@code{shortterm}. By default the momentary value will be used, but in certain
scenarios it may be more useful to observe the short term value instead (e.g.
live mixing).
@end table @end table
@subsection Examples @subsection Examples
......
...@@ -143,6 +143,7 @@ typedef struct EBUR128Context { ...@@ -143,6 +143,7 @@ typedef struct EBUR128Context {
int dual_mono; ///< whether or not to treat single channel input files as dual-mono int dual_mono; ///< whether or not to treat single channel input files as dual-mono
double pan_law; ///< pan law value used to calculate dual-mono measurements double pan_law; ///< pan law value used to calculate dual-mono measurements
int target; ///< target level in LUFS used to set relative zero LU in visualization int target; ///< target level in LUFS used to set relative zero LU in visualization
int gauge_type; ///< whether gauge shows momentary or short
} EBUR128Context; } EBUR128Context;
enum { enum {
...@@ -151,6 +152,12 @@ enum { ...@@ -151,6 +152,12 @@ enum {
PEAK_MODE_TRUE_PEAKS = 1<<2, PEAK_MODE_TRUE_PEAKS = 1<<2,
}; };
enum {
GAUGE_TYPE_MOMENTARY = 0,
GAUGE_TYPE_SHORTTERM = 1,
};
#define OFFSET(x) offsetof(EBUR128Context, x) #define OFFSET(x) offsetof(EBUR128Context, x)
#define A AV_OPT_FLAG_AUDIO_PARAM #define A AV_OPT_FLAG_AUDIO_PARAM
#define V AV_OPT_FLAG_VIDEO_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM
...@@ -170,6 +177,11 @@ static const AVOption ebur128_options[] = { ...@@ -170,6 +177,11 @@ static const AVOption ebur128_options[] = {
{ "dualmono", "treat mono input files as dual-mono", OFFSET(dual_mono), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A|F }, { "dualmono", "treat mono input files as dual-mono", OFFSET(dual_mono), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A|F },
{ "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 }, { "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 },
{ "target", "set a specific target level in LUFS (-23 to 0)", OFFSET(target), AV_OPT_TYPE_INT, {.i64 = -23}, -23, 0, V|F }, { "target", "set a specific target level in LUFS (-23 to 0)", OFFSET(target), AV_OPT_TYPE_INT, {.i64 = -23}, -23, 0, V|F },
{ "gauge", "set gauge display type", OFFSET(gauge_type), AV_OPT_TYPE_INT, {.i64 = 0 }, GAUGE_TYPE_MOMENTARY, GAUGE_TYPE_SHORTTERM, V|F, "gaugetype" },
{ "momentary", "display momentary value", 0, AV_OPT_TYPE_CONST, {.i64 = GAUGE_TYPE_MOMENTARY}, INT_MIN, INT_MAX, V|F, "gaugetype" },
{ "m", "display momentary value", 0, AV_OPT_TYPE_CONST, {.i64 = GAUGE_TYPE_MOMENTARY}, INT_MIN, INT_MAX, V|F, "gaugetype" },
{ "shortterm", "display short-term value", 0, AV_OPT_TYPE_CONST, {.i64 = GAUGE_TYPE_SHORTTERM}, INT_MIN, INT_MAX, V|F, "gaugetype" },
{ "s", "display short-term value", 0, AV_OPT_TYPE_CONST, {.i64 = GAUGE_TYPE_SHORTTERM}, INT_MIN, INT_MAX, V|F, "gaugetype" },
{ NULL }, { NULL },
}; };
...@@ -741,9 +753,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) ...@@ -741,9 +753,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
if (ebur128->do_video) { if (ebur128->do_video) {
int x, y, ret; int x, y, ret;
uint8_t *p; uint8_t *p;
double gauge_value;
if (ebur128->gauge_type == GAUGE_TYPE_MOMENTARY) {
gauge_value = loudness_400 - ebur128->target;
} else {
gauge_value = loudness_3000 - ebur128->target;
}
const int y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 - ebur128->target); const int y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 - ebur128->target);
const int y_loudness_lu_gauge = lu_to_y(ebur128, loudness_400 - ebur128->target); const int y_loudness_lu_gauge = lu_to_y(ebur128, gauge_value);
/* draw the graph using the short-term loudness */ /* draw the graph using the short-term loudness */
p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3;
...@@ -755,7 +774,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) ...@@ -755,7 +774,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
p += pic->linesize[0]; p += pic->linesize[0];
} }
/* draw the gauge using the momentary loudness */ /* draw the gauge using either momentary or short-term loudness */
p = pic->data[0] + ebur128->gauge.y*pic->linesize[0] + ebur128->gauge.x*3; p = pic->data[0] + ebur128->gauge.y*pic->linesize[0] + ebur128->gauge.x*3;
for (y = 0; y < ebur128->gauge.h; y++) { for (y = 0; y < ebur128->gauge.h; y++) {
const uint8_t *c = get_graph_color(ebur128, y_loudness_lu_gauge, y); const uint8_t *c = get_graph_color(ebur128, y_loudness_lu_gauge, y);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment