[FFmpeg-devel] [PATCH 0/5] Improvements for EBU R128 plugin
Hi, we are using ffmpeg to monitor audio for use in online video production. In order to make this more practical, we added a couple of features to the ebur128 with the help from audio professionals. Please let me know if they are good for going into master, and if you would like to see any changes before they can be merged. Cheers, Daniel Daniel Molkentin (5): libavfilter/ebur128: add target level option for EBUR128 visualization filter libavfilter/ebur128: add target value to statistics line libavfilter/ebur128: add gaugetype option libavfilter/ebur128: introduce target range libavfilter/ebur128: add mabsolute parameter doc/filters.texi| 21 +- libavfilter/f_ebur128.c | 89 +++-- 2 files changed, 87 insertions(+), 23 deletions(-) -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 3/5] libavfilter/ebur128: add gaugetype option
Allow to show short term instead of momentary. Useful for monitoring whilst live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 8 +++- libavfilter/f_ebur128.c | 18 -- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index bd5154f9be..40d9006075 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19279,7 +19279,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, 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 -the momentary loudness (400 milliseconds). +the momentary loudness (400 milliseconds), but can optionally be configured +to instead display short-term loundness (see @var{gaugetype}). More information about the Loudness Recommendation EBU R128 on @url{http://tech.ebu.ch/loudness}. @@ -19362,6 +19363,11 @@ 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 by EBU R128. However, material published online may prefer a level of -16LUFS (e.g. for use with podcasts or video platforms). + +@item gaugetype +Set the value displayed by the gauge. Valid values are m (momentary) and s (short-term). +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 @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 89bfcb0b3e..66d4c4dec7 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -143,6 +143,7 @@ typedef struct EBUR128Context { 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 int target; ///< target level in LUFS used to set relative zero LU in visualization +char *gauge_type; ///< whether gauge shows momentary or short } EBUR128Context; enum { @@ -170,6 +171,7 @@ 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 }, { "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 }, +{ "gaugetype", "sets whether the gauge shows momentrary (m) or short-term (s)", OFFSET(gauge_type), AV_OPT_TYPE_STRING, {.str = "m"}, CHAR_MIN, CHAR_MAX, V|F }, { NULL }, }; @@ -517,6 +519,11 @@ static av_cold int init(AVFilterContext *ctx) return ret; } +if (strcmp(ebur128->gauge_type, "m") && strcmp(ebur128->gauge_type, "s")) { +av_log(ctx, AV_LOG_ERROR, "Value for gaugetype can only be 'm' or 's'.\n"); +return AVERROR(EINVAL); +} + /* summary */ av_log(ctx, AV_LOG_VERBOSE, "EBU +%d scale\n", ebur128->meter); @@ -741,9 +748,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) if (ebur128->do_video) { int x, y, ret; uint8_t *p; +double gauge_value; + +if (!strcmp(ebur128->gauge_type, "m")) { +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_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 */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; @@ -755,7 +769,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) 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; for (y = 0; y < ebur128->gauge.h; y++) { const uint8_t *c = get_graph_color(ebur128, y_loudness_lu_gauge, y); -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/5] libavfilter/ebur128: add target level option for EBUR128 visualization filter
Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 6 ++ libavfilter/f_ebur128.c | 6 -- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 30a52c4fdb..bd5154f9be 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19356,6 +19356,12 @@ Multi-channel input files are not affected by this option. @item panlaw Set a specific pan law to be used for the measurement of dual mono files. This parameter is optional, and has a default value of -3.01dB. + +@item target +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 +by EBU R128. However, material published online may prefer a level of -16LUFS +(e.g. for use with podcasts or video platforms). @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index a48d3629ce..dfccbff5ec 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -142,6 +142,7 @@ typedef struct EBUR128Context { int metadata; ///< whether or not to inject loudness results in frames 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 +int target; ///< target level in LUFS used to set relative zero LU in visualization } EBUR128Context; enum { @@ -168,6 +169,7 @@ static const AVOption ebur128_options[] = { { "true", "enable true-peak mode", 0, AV_OPT_TYPE_CONST, {.i64 = PEAK_MODE_TRUE_PEAKS},INT_MIN, INT_MAX, A|F, "mode" }, { "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 }, +{ "target", "set a specific target level in LUFS (-23 to 0)", OFFSET(target), AV_OPT_TYPE_INT, {.i64 = -23}, -23, 0, V|F }, { NULL }, }; @@ -740,8 +742,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) int x, y, ret; uint8_t *p; -const int y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 + 23); -const int y_loudness_lu_gauge = lu_to_y(ebur128, loudness_400 + 23); +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); /* draw the graph using the short-term loudness */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/5] libavfilter/ebur128: add target value to statistics line
Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- libavfilter/f_ebur128.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index dfccbff5ec..89bfcb0b3e 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -735,7 +735,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) loudness_3000 -= ebur128->pan_law; } -#define LOG_FMT "M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" +#define LOG_FMT "TARGET:%d M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" /* push one video frame */ if (ebur128->do_video) { @@ -768,7 +768,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* draw textual info */ drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, LOG_FMT " ", // padding to erase trailing characters - loudness_400, loudness_3000, + ebur128->target, loudness_400, loudness_3000, ebur128->integrated_loudness, ebur128->loudness_range); /* set pts and push frame */ @@ -811,7 +811,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT, av_ts2timestr(pts, &outlink->time_base), - loudness_400, loudness_3000, + ebur128->target, loudness_400, loudness_3000, ebur128->integrated_loudness, ebur128->loudness_range); #define PRINT_PEAKS(str, sp, ptype) do {\ -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 4/5] libavfilter/ebur128: introduce target range
This eases meeting the target level during live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 3 +++ libavfilter/f_ebur128.c | 33 +++-- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 40d9006075..601cbda17c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19282,6 +19282,9 @@ short-term loudness (3 seconds of analysis), and the gauge on the right is for the momentary loudness (400 milliseconds), but can optionally be configured to instead display short-term loundness (see @var{gaugetype}). +The green area marks a +/- 1LU target range around the target loudness +(-23LUFS by default, unless modified through @var{target}). + More information about the Loudness Recommendation EBU R128 on @url{http://tech.ebu.ch/loudness}. diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 66d4c4dec7..182e0cbe98 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -114,6 +114,8 @@ typedef struct EBUR128Context { int meter; ///< select a EBU mode between +9 and +18 int scale_range;///< the range of LU values according to the meter int y_zero_lu; ///< the y value (pixel position) for 0 LU +int y_opt_max; ///< the y value (pixel position) for 1 LU +int y_opt_min; ///< the y value (pixel position) for -1 LU int *y_line_ref;///< y reference values for drawing the LU lines in the graph and the gauge /* audio */ @@ -178,22 +180,31 @@ static const AVOption ebur128_options[] = { AVFILTER_DEFINE_CLASS(ebur128); static const uint8_t graph_colors[] = { -0xdd, 0x66, 0x66, // value above 0LU non reached -0x66, 0x66, 0xdd, // value below 0LU non reached -0x96, 0x33, 0x33, // value above 0LU reached -0x33, 0x33, 0x96, // value below 0LU reached -0xdd, 0x96, 0x96, // value above 0LU line non reached -0x96, 0x96, 0xdd, // value below 0LU line non reached -0xdd, 0x33, 0x33, // value above 0LU line reached -0x33, 0x33, 0xdd, // value below 0LU line reached +0xdd, 0x66, 0x66, // value above 1LU non reached below -1LU (impossible) +0x66, 0x66, 0xdd, // value below 1LU non reached below -1LU +0x96, 0x33, 0x33, // value above 1LU reached below -1LU (impossible) +0x33, 0x33, 0x96, // value below 1LU reached below -1LU +0xdd, 0x96, 0x96, // value above 1LU line non reached below -1LU (impossible) +0x96, 0x96, 0xdd, // value below 1LU line non reached below -1LU +0xdd, 0x33, 0x33, // value above 1LU line reached below -1LU (impossible) +0x33, 0x33, 0xdd, // value below 1LU line reached below -1LU +0xdd, 0x66, 0x66, // value above 1LU non reached above -1LU +0x66, 0xdd, 0x66, // value below 1LU non reached above -1LU +0x96, 0x33, 0x33, // value above 1LU reached above -1LU +0x33, 0x96, 0x33, // value below 1LU reached above -1LU +0xdd, 0x96, 0x96, // value above 1LU line non reached above -1LU +0x96, 0xdd, 0x96, // value below 1LU line non reached above -1LU +0xdd, 0x33, 0x33, // value above 1LU line reached above -1LU +0x33, 0xdd, 0x33, // value below 1LU line reached above -1LU }; static const uint8_t *get_graph_color(const EBUR128Context *ebur128, int v, int y) { -const int below0 = y > ebur128->y_zero_lu; +const int above_opt_max = y > ebur128->y_opt_max; +const int below_opt_min = y < ebur128->y_opt_min; const int reached = y >= v; const int line= ebur128->y_line_ref[y] || y == ebur128->y_zero_lu; -const int colorid = 4*line + 2*reached + below0; +const int colorid = 8*below_opt_min+ 4*line + 2*reached + above_opt_max; return graph_colors + 3*colorid; } @@ -327,6 +338,8 @@ static int config_video_output(AVFilterLink *outlink) /* draw graph */ ebur128->y_zero_lu = lu_to_y(ebur128, 0); +ebur128->y_opt_max = lu_to_y(ebur128, 1); +ebur128->y_opt_min = lu_to_y(ebur128, -1); p = outpicref->data[0] + ebur128->graph.y * outpicref->linesize[0] + ebur128->graph.x * 3; for (y = 0; y < ebur128->graph.h; y++) { -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 5/5] libavfilter/ebur128: add mabsolute parameter
This allows switching between absolute (LUFS) and relativ (LU) display in the status line. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 4 libavfilter/f_ebur128.c | 34 +- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 601cbda17c..dc01c805b2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19371,6 +19371,10 @@ by EBU R128. However, material published online may prefer a level of -16LUFS Set the value displayed by the gauge. Valid values are m (momentary) and s (short-term). 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). + +@item mabsolute +Sets whether to display the loudness in LUFS (1, the default) LU relative to the target (0). +This only affects the video output, not the summary or continous log output. @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 182e0cbe98..5d58abc741 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -146,6 +146,7 @@ typedef struct EBUR128Context { 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 char *gauge_type; ///< whether gauge shows momentary or short +int mabsolute; ///< whether to display the statistics in LUFS or LU } EBUR128Context; enum { @@ -174,6 +175,7 @@ static const AVOption ebur128_options[] = { { "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 }, { "gaugetype", "sets whether the gauge shows momentrary (m) or short-term (s)", OFFSET(gauge_type), AV_OPT_TYPE_STRING, {.str = "m"}, CHAR_MIN, CHAR_MAX, V|F }, +{ "mabsolute", "sets whether the stats should be displayed absolute (LUFS, default) or relative (LU) ", OFFSET(mabsolute), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, V|F }, { NULL }, }; @@ -755,7 +757,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) loudness_3000 -= ebur128->pan_law; } -#define LOG_FMT "TARGET:%d M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" +#define LOG_FMT "TARGET:%d LUFSM:%6.1f S:%6.1f I:%6.1f %s LRA:%6.1f LU" /* push one video frame */ if (ebur128->do_video) { @@ -793,10 +795,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } /* draw textual info */ -drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, - LOG_FMT " ", // padding to erase trailing characters - ebur128->target, loudness_400, loudness_3000, - ebur128->integrated_loudness, ebur128->loudness_range); +if (ebur128->mabsolute) { +drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, + LOG_FMT " ", // padding to erase trailing characters + ebur128->target, loudness_400, loudness_3000, + ebur128->integrated_loudness, "LUFS", ebur128->loudness_range); +} else { +drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, + LOG_FMT " ", // padding to erase trailing characters + ebur128->target, loudness_400-ebur128->target, loudness_3000-ebur128->target, + ebur128->integrated_loudness-ebur128->target, "LU", ebur128->loudness_range); +} /* set pts and push frame */ pic->pts = pts; @@ -836,10 +845,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) SET_META_PEAK(true, TRUE); } -av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT, - av_ts2timestr(pts, &outlink->time_base), - ebur128->target, loudness_400, loudness_3000, - ebur128->integrated_loudness, ebur128->loudness_range); +if (ebur128->mabsolute) { +av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT, + av_ts2timestr(pts, &outlink->time_base), + ebur128->targ
[FFmpeg-devel] [PATCH 3/5] libavfilter/ebur128: add gaugetype option
Allow to show short term instead of momentary. Useful for monitoring whilst live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 9 - libavfilter/f_ebur128.c | 21 +++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index bd5154f9be..0363daffbb 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19279,7 +19279,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, 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 -the momentary loudness (400 milliseconds). +the momentary loudness (400 milliseconds), but can optionally be configured +to instead display short-term loundness (see @var{gaugetype}). More information about the Loudness Recommendation EBU R128 on @url{http://tech.ebu.ch/loudness}. @@ -19362,6 +19363,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 by EBU R128. However, material published online may prefer a level of -16LUFS (e.g. for use with podcasts or video platforms). + +@item gaugetype +Set the value displayed by the gauge. Valid values are @code{momentary} and s +@code{short-term}. 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 @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 89bfcb0b3e..9fd4bcef0a 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -143,6 +143,7 @@ typedef struct EBUR128Context { 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 int target; ///< target level in LUFS used to set relative zero LU in visualization +char *gauge_type; ///< whether gauge shows momentary or short } EBUR128Context; enum { @@ -151,6 +152,12 @@ enum { PEAK_MODE_TRUE_PEAKS= 1<<2, }; +enum { +GAUGE_TYPE_MOMENTARY = 0, +GAUGE_TYPE_SHORTTERM = 1, +}; + + #define OFFSET(x) offsetof(EBUR128Context, x) #define A AV_OPT_FLAG_AUDIO_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM @@ -170,6 +177,9 @@ 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 }, { "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 }, +{ "gaugetype", "set gauge display type", OFFSET(gauge_type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|F, "type" }, +{ "momentary", "display momentary value", 0, AV_OPT_TYPE_CONST, {.i64 = GAUGE_TYPE_MOMENTARY}, INT_MIN, INT_MAX, V|F, "type" }, +{ "shortterm", "display short-term value", 0, AV_OPT_TYPE_CONST, {.i64 = GAUGE_TYPE_SHORTTERM}, INT_MIN, INT_MAX, V|F, "type" }, { NULL }, }; @@ -741,9 +751,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) if (ebur128->do_video) { int x, y, ret; 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_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 */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; @@ -755,7 +772,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) 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->
Re: [FFmpeg-devel] [PATCH 5/5] libavfilter/ebur128: add mabsolute parameter
On 07.10.2018 18:02, Daniel Molkentin wrote: > This allows switching between absolute (LUFS) and relativ (LU) display > in the status line. > > Signed-off-by: Daniel Molkentin > Signed-off-by: Conrad Zelck > --- > doc/filters.texi| 4 > libavfilter/f_ebur128.c | 34 +- > 2 files changed, 29 insertions(+), 9 deletions(-) > > diff --git a/doc/filters.texi b/doc/filters.texi > index 601cbda17c..dc01c805b2 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -19371,6 +19371,10 @@ by EBU R128. However, material published online may > prefer a level of -16LUFS > Set the value displayed by the gauge. Valid values are m (momentary) and s > (short-term). > 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). > + > +@item mabsolute > +Sets whether to display the loudness in LUFS (1, the default) LU relative to > the target (0). > +This only affects the video output, not the summary or continous log output. > @end table > On a second thought, should this maybe be measurement=absolute|relative or measurement=LU|LUFS? Opinions? More descriptive that way... Cheers, Daniel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 5/5] libavfilter/ebur128: add mabsolute parameter
On 07.10.2018 21:37, Marton Balint wrote: > > > On Sun, 7 Oct 2018, Daniel Molkentin wrote: > >> >> On 07.10.2018 18:02, Daniel Molkentin wrote: >>> This allows switching between absolute (LUFS) and relativ (LU) display >>> in the status line. >>> >>> Signed-off-by: Daniel Molkentin >>> Signed-off-by: Conrad Zelck >>> --- >>> doc/filters.texi | 4 >>> libavfilter/f_ebur128.c | 34 +- >>> 2 files changed, 29 insertions(+), 9 deletions(-) >>> >>> diff --git a/doc/filters.texi b/doc/filters.texi >>> index 601cbda17c..dc01c805b2 100644 >>> --- a/doc/filters.texi >>> +++ b/doc/filters.texi >>> @@ -19371,6 +19371,10 @@ by EBU R128. However, material published >>> online may prefer a level of -16LUFS >>> Set the value displayed by the gauge. Valid values are m >>> (momentary) and s (short-term). >>> 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). >>> + >>> +@item mabsolute >>> +Sets whether to display the loudness in LUFS (1, the default) LU >>> relative to the target (0). >>> +This only affects the video output, not the summary or continous >>> log output. >>> @end table >>> >> On a second thought, should this maybe be measurement=absolute|relative >> or measurement=LU|LUFS? Opinions? More descriptive that way... > > scale=absolute/relative > > IMHO that makes it the most descriptive. We thought about that, but the first association we thought people might have when confronted with the word scale are the histogram labels with the LU values on the right, (which are untouched by this option). I am fine with either. Cheers, Daniel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 4/5] libavfilter/ebur128: introduce target range
This eases meeting the target level during live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 8 libavfilter/f_ebur128.c | 33 +++-- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 7f2baed9b5..875b412f41 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19284,6 +19284,9 @@ short-term loudness (3 seconds of analysis), and the gauge on the right is for the momentary loudness (400 milliseconds), but can optionally be configured to instead display short-term loudness (see @var{gauge}). +The green area marks a +/- 1LU target range around the target loudness +(-23LUFS by default, unless modified through @var{target}). + More information about the Loudness Recommendation EBU R128 on @url{http://tech.ebu.ch/loudness}. @@ -19371,6 +19374,11 @@ 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). + +@item mabsolute +Sets whether to display the loudness in LUFS (1, the default) LU relative to +the target (0). This only affects the video output, not the summary or +continous log output. @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 10dc717960..53f21c9d14 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -114,6 +114,8 @@ typedef struct EBUR128Context { int meter; ///< select a EBU mode between +9 and +18 int scale_range;///< the range of LU values according to the meter int y_zero_lu; ///< the y value (pixel position) for 0 LU +int y_opt_max; ///< the y value (pixel position) for 1 LU +int y_opt_min; ///< the y value (pixel position) for -1 LU int *y_line_ref;///< y reference values for drawing the LU lines in the graph and the gauge /* audio */ @@ -186,22 +188,31 @@ static const AVOption ebur128_options[] = { AVFILTER_DEFINE_CLASS(ebur128); static const uint8_t graph_colors[] = { -0xdd, 0x66, 0x66, // value above 0LU non reached -0x66, 0x66, 0xdd, // value below 0LU non reached -0x96, 0x33, 0x33, // value above 0LU reached -0x33, 0x33, 0x96, // value below 0LU reached -0xdd, 0x96, 0x96, // value above 0LU line non reached -0x96, 0x96, 0xdd, // value below 0LU line non reached -0xdd, 0x33, 0x33, // value above 0LU line reached -0x33, 0x33, 0xdd, // value below 0LU line reached +0xdd, 0x66, 0x66, // value above 1LU non reached below -1LU (impossible) +0x66, 0x66, 0xdd, // value below 1LU non reached below -1LU +0x96, 0x33, 0x33, // value above 1LU reached below -1LU (impossible) +0x33, 0x33, 0x96, // value below 1LU reached below -1LU +0xdd, 0x96, 0x96, // value above 1LU line non reached below -1LU (impossible) +0x96, 0x96, 0xdd, // value below 1LU line non reached below -1LU +0xdd, 0x33, 0x33, // value above 1LU line reached below -1LU (impossible) +0x33, 0x33, 0xdd, // value below 1LU line reached below -1LU +0xdd, 0x66, 0x66, // value above 1LU non reached above -1LU +0x66, 0xdd, 0x66, // value below 1LU non reached above -1LU +0x96, 0x33, 0x33, // value above 1LU reached above -1LU +0x33, 0x96, 0x33, // value below 1LU reached above -1LU +0xdd, 0x96, 0x96, // value above 1LU line non reached above -1LU +0x96, 0xdd, 0x96, // value below 1LU line non reached above -1LU +0xdd, 0x33, 0x33, // value above 1LU line reached above -1LU +0x33, 0xdd, 0x33, // value below 1LU line reached above -1LU }; static const uint8_t *get_graph_color(const EBUR128Context *ebur128, int v, int y) { -const int below0 = y > ebur128->y_zero_lu; +const int above_opt_max = y > ebur128->y_opt_max; +const int below_opt_min = y < ebur128->y_opt_min; const int reached = y >= v; const int line= ebur128->y_line_ref[y] || y == ebur128->y_zero_lu; -const int colorid = 4*line + 2*reached + below0; +const int colorid = 8*below_opt_min+ 4*line + 2*reached + above_opt_max; return graph_colors + 3*colorid; } @@ -335,6 +346,8 @@ static int config_video_output(AVFilterLink *outlink) /* draw graph */ ebur128->y_zero_lu = lu_to_y(ebur128, 0); +ebur128->y_opt_max = lu_to_y(ebur128, 1); +ebur128->y_opt_min = lu_to_y(ebur128, -1); p = outpicref->data[0] + ebur128->graph.y * outpicref->linesize[0] + ebur128->graph.x * 3; for (y = 0; y < ebur128->graph.h; y++) { -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 3/5] libavfilter/ebur128: add gauge option
Allow to show short-term instead of momentary in gauge. Useful for monitoring whilst live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 9 - libavfilter/f_ebur128.c | 21 +++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 86ea25bda8..7f2baed9b5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -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, 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 -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 @url{http://tech.ebu.ch/loudness}. @@ -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 by EBU R128. However, material published online may prefer a level of -16LUFS (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 @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 89bfcb0b3e..10dc717960 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -143,6 +143,7 @@ typedef struct EBUR128Context { 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 int target; ///< target level in LUFS used to set relative zero LU in visualization +int gauge_type; ///< whether gauge shows momentary or short } EBUR128Context; enum { @@ -151,6 +152,12 @@ enum { PEAK_MODE_TRUE_PEAKS= 1<<2, }; +enum { +GAUGE_TYPE_MOMENTARY = 0, +GAUGE_TYPE_SHORTTERM = 1, +}; + + #define OFFSET(x) offsetof(EBUR128Context, x) #define A AV_OPT_FLAG_AUDIO_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM @@ -170,6 +177,9 @@ 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 }, { "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 }, +{ "gauge", "set gauge display type", OFFSET(gauge_type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|F, "gaugetype" }, +{ "momentary", "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" }, { NULL }, }; @@ -741,9 +751,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) if (ebur128->do_video) { int x, y, ret; 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_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 */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; @@ -755,7 +772,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) 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->
[FFmpeg-devel] [PATCH 0/5] Improvements for EBU R128 plugin (second round)
Changes over first patchset: Mainly wording. Use full words as a parameter values. Switch to constants instead of strings for parameters. Also: - "mabsolute" bool parameter renamed "scale" as per reviewer suggestion - "gaugetype" parameter renamed to "gauge" for consistency with scale - typo fixes in documentation Cheers, Daniel Daniel Molkentin (5): libavfilter/ebur128: add target level option for EBUR128 visualization filter libavfilter/ebur128: add target value to statistics line libavfilter/ebur128: add gauge option libavfilter/ebur128: introduce target range libavfilter/ebur128: add scale parameter doc/filters.texi| 23 - libavfilter/f_ebur128.c | 100 +++- 2 files changed, 100 insertions(+), 23 deletions(-) -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/5] libavfilter/ebur128: add target level option for EBUR128 visualization filter
Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 6 ++ libavfilter/f_ebur128.c | 6 -- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index b523877cf3..86ea25bda8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19358,6 +19358,12 @@ Multi-channel input files are not affected by this option. @item panlaw Set a specific pan law to be used for the measurement of dual mono files. This parameter is optional, and has a default value of -3.01dB. + +@item target +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 +by EBU R128. However, material published online may prefer a level of -16LUFS +(e.g. for use with podcasts or video platforms). @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index a48d3629ce..dfccbff5ec 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -142,6 +142,7 @@ typedef struct EBUR128Context { int metadata; ///< whether or not to inject loudness results in frames 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 +int target; ///< target level in LUFS used to set relative zero LU in visualization } EBUR128Context; enum { @@ -168,6 +169,7 @@ static const AVOption ebur128_options[] = { { "true", "enable true-peak mode", 0, AV_OPT_TYPE_CONST, {.i64 = PEAK_MODE_TRUE_PEAKS},INT_MIN, INT_MAX, A|F, "mode" }, { "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 }, +{ "target", "set a specific target level in LUFS (-23 to 0)", OFFSET(target), AV_OPT_TYPE_INT, {.i64 = -23}, -23, 0, V|F }, { NULL }, }; @@ -740,8 +742,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) int x, y, ret; uint8_t *p; -const int y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 + 23); -const int y_loudness_lu_gauge = lu_to_y(ebur128, loudness_400 + 23); +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); /* draw the graph using the short-term loudness */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/5] libavfilter/ebur128: add target value to statistics line
Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- libavfilter/f_ebur128.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index dfccbff5ec..89bfcb0b3e 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -735,7 +735,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) loudness_3000 -= ebur128->pan_law; } -#define LOG_FMT "M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" +#define LOG_FMT "TARGET:%d M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" /* push one video frame */ if (ebur128->do_video) { @@ -768,7 +768,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* draw textual info */ drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, LOG_FMT " ", // padding to erase trailing characters - loudness_400, loudness_3000, + ebur128->target, loudness_400, loudness_3000, ebur128->integrated_loudness, ebur128->loudness_range); /* set pts and push frame */ @@ -811,7 +811,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT, av_ts2timestr(pts, &outlink->time_base), - loudness_400, loudness_3000, + ebur128->target, loudness_400, loudness_3000, ebur128->integrated_loudness, ebur128->loudness_range); #define PRINT_PEAKS(str, sp, ptype) do {\ -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 5/5] libavfilter/ebur128: add scale parameter
This allows switching between absolute (LUFS) and relativ (LU) display in the status line. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 8 libavfilter/f_ebur128.c | 42 - 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 875b412f41..df957fda0f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19375,10 +19375,10 @@ Set the value displayed by the gauge. Valid values are @code{momentary} and s scenarios it may be more useful to observe the short term value instead (e.g. live mixing). -@item mabsolute -Sets whether to display the loudness in LUFS (1, the default) LU relative to -the target (0). This only affects the video output, not the summary or -continous log output. +@item scale +Sets the display scale for the loudness. Valid parameters are @code{absolute} +(in LUFS) or @code{relative} (LU) relative to the target. This only affects the +video output, not the summary or continous log output. @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 53f21c9d14..259d2036fc 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -146,6 +146,7 @@ typedef struct EBUR128Context { 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 gauge_type; ///< whether gauge shows momentary or short +int scale; ///< display scale type of statistics } EBUR128Context; enum { @@ -159,6 +160,10 @@ enum { GAUGE_TYPE_SHORTTERM = 1, }; +enum { +SCALE_TYPE_ABSOLUTE = 0, +SCALE_TYPE_RELATIVE = 1, +}; #define OFFSET(x) offsetof(EBUR128Context, x) #define A AV_OPT_FLAG_AUDIO_PARAM @@ -182,6 +187,11 @@ static const AVOption ebur128_options[] = { { "gauge", "set gauge display type", OFFSET(gauge_type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|F, "gaugetype" }, { "momentary", "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" }, +{ "scale", "sets display method for the stats", OFFSET(scale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, V|F, "scaletype" }, +{ "absolute", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, +{ "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, +{ "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, +{ "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, { NULL }, }; @@ -758,7 +768,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) loudness_3000 -= ebur128->pan_law; } -#define LOG_FMT "TARGET:%d M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" +#define LOG_FMT "TARGET:%d LUFSM:%6.1f S:%6.1f I:%6.1f %s LRA:%6.1f LU" /* push one video frame */ if (ebur128->do_video) { @@ -796,10 +806,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } /* draw textual info */ -drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, - LOG_FMT " ", // padding to erase trailing characters - ebur128->target, loudness_400, loudness_3000, - ebur128->integrated_loudness, ebur128->loudness_range); +if (ebur128->scale == SCALE_TYPE_ABSOLUTE) { +drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, + LOG_FMT " ", // padding to erase trailing characters + ebur128->target, loudness_400, loudness_3000, + ebur128->integrated_loudness, "LUFS", ebur128->loudness_range); +} else { +drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, + LOG_FMT " ", // padding to erase trailing characte
Re: [FFmpeg-devel] [PATCH 5/5] libavfilter/ebur128: add scale parameter
On 08.10.2018 21:00, Carl Eugen Hoyos wrote: > 2018-10-08 9:21 GMT+02:00, Moritz Barsnick : > >> Adding options (and changing output line format?) might also warrant a >> micro-version bump of lavfi > It does. > Even more so for the changed output line... If you point me to where it needs bumping, I'll include it in the next revision of the patchset Cheers, Daniel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/6] libavfilter/ebur128: add target value to statistics line
Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- libavfilter/f_ebur128.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index dfccbff5ec..89bfcb0b3e 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -735,7 +735,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) loudness_3000 -= ebur128->pan_law; } -#define LOG_FMT "M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" +#define LOG_FMT "TARGET:%d M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" /* push one video frame */ if (ebur128->do_video) { @@ -768,7 +768,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* draw textual info */ drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, LOG_FMT " ", // padding to erase trailing characters - loudness_400, loudness_3000, + ebur128->target, loudness_400, loudness_3000, ebur128->integrated_loudness, ebur128->loudness_range); /* set pts and push frame */ @@ -811,7 +811,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT, av_ts2timestr(pts, &outlink->time_base), - loudness_400, loudness_3000, + ebur128->target, loudness_400, loudness_3000, ebur128->integrated_loudness, ebur128->loudness_range); #define PRINT_PEAKS(str, sp, ptype) do {\ -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/6] libavfilter/ebur128: add target level option for EBUR128 visualization filter
Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 6 ++ libavfilter/f_ebur128.c | 6 -- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index b523877cf3..86ea25bda8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19358,6 +19358,12 @@ Multi-channel input files are not affected by this option. @item panlaw Set a specific pan law to be used for the measurement of dual mono files. This parameter is optional, and has a default value of -3.01dB. + +@item target +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 +by EBU R128. However, material published online may prefer a level of -16LUFS +(e.g. for use with podcasts or video platforms). @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index a48d3629ce..dfccbff5ec 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -142,6 +142,7 @@ typedef struct EBUR128Context { int metadata; ///< whether or not to inject loudness results in frames 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 +int target; ///< target level in LUFS used to set relative zero LU in visualization } EBUR128Context; enum { @@ -168,6 +169,7 @@ static const AVOption ebur128_options[] = { { "true", "enable true-peak mode", 0, AV_OPT_TYPE_CONST, {.i64 = PEAK_MODE_TRUE_PEAKS},INT_MIN, INT_MAX, A|F, "mode" }, { "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 }, +{ "target", "set a specific target level in LUFS (-23 to 0)", OFFSET(target), AV_OPT_TYPE_INT, {.i64 = -23}, -23, 0, V|F }, { NULL }, }; @@ -740,8 +742,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) int x, y, ret; uint8_t *p; -const int y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 + 23); -const int y_loudness_lu_gauge = lu_to_y(ebur128, loudness_400 + 23); +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); /* draw the graph using the short-term loudness */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 0/6] Improvements for EBU R128 plugin (third round)
Changes over second round: - gauge option: Add 'm' and 's' as alias parameter for momentary and short-term - fix spelling error in documentation - remove "mabsolute" documentation which was added to the range patch by accident - fixed ranges for parameters - bumped micro version for libavfilter Daniel Molkentin (6): libavfilter/ebur128: add target level option for EBUR128 visualization filter libavfilter/ebur128: add target value to statistics line libavfilter/ebur128: add gauge option libavfilter/ebur128: introduce target range libavfilter/ebur128: add scale parameter libavfilter: Bump micro version to 101 doc/filters.texi| 23 - libavfilter/f_ebur128.c | 102 +++- libavfilter/version.h | 2 +- 3 files changed, 103 insertions(+), 24 deletions(-) -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 5/6] libavfilter/ebur128: add scale parameter
This allows switching between absolute (LUFS) and relativ (LU) display in the status line. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 5 + libavfilter/f_ebur128.c | 42 - 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 3783a8a421..c0e785 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19374,6 +19374,11 @@ 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). + +@item scale +Sets the display scale for the loudness. Valid parameters are @code{absolute} +(in LUFS) or @code{relative} (LU) relative to the target. This only affects the +video output, not the summary or continuous log output. @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 688c7bf135..d481e479b0 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -146,6 +146,7 @@ typedef struct EBUR128Context { 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 gauge_type; ///< whether gauge shows momentary or short +int scale; ///< display scale type of statistics } EBUR128Context; enum { @@ -159,6 +160,10 @@ enum { GAUGE_TYPE_SHORTTERM = 1, }; +enum { +SCALE_TYPE_ABSOLUTE = 0, +SCALE_TYPE_RELATIVE = 1, +}; #define OFFSET(x) offsetof(EBUR128Context, x) #define A AV_OPT_FLAG_AUDIO_PARAM @@ -184,6 +189,11 @@ static const AVOption ebur128_options[] = { { "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" }, +{ "scale", "sets display method for the stats", OFFSET(scale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, V|F, "scaletype" }, +{ "absolute", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, +{ "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, +{ "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, +{ "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, { NULL }, }; @@ -760,7 +770,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) loudness_3000 -= ebur128->pan_law; } -#define LOG_FMT "TARGET:%d M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU" +#define LOG_FMT "TARGET:%d LUFSM:%6.1f S:%6.1f I:%6.1f %s LRA:%6.1f LU" /* push one video frame */ if (ebur128->do_video) { @@ -798,10 +808,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } /* draw textual info */ -drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, - LOG_FMT " ", // padding to erase trailing characters - ebur128->target, loudness_400, loudness_3000, - ebur128->integrated_loudness, ebur128->loudness_range); +if (ebur128->scale == SCALE_TYPE_ABSOLUTE) { +drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, + LOG_FMT " ", // padding to erase trailing characters + ebur128->target, loudness_400, loudness_3000, + ebur128->integrated_loudness, "LUFS", ebur128->loudness_range); +} else { +drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors, + LOG_FMT " ", // padding to erase trailing characters + ebur128->target, loudness_400-ebu
[FFmpeg-devel] [PATCH 6/6] libavfilter: bump micro version to 101
--- libavfilter/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/version.h b/libavfilter/version.h index cde68fbdd5..30e961b999 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 33 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 4/6] libavfilter/ebur128: introduce target range
This eases meeting the target level during live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 3 +++ libavfilter/f_ebur128.c | 33 +++-- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 7f2baed9b5..3783a8a421 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19284,6 +19284,9 @@ short-term loudness (3 seconds of analysis), and the gauge on the right is for the momentary loudness (400 milliseconds), but can optionally be configured to instead display short-term loudness (see @var{gauge}). +The green area marks a +/- 1LU target range around the target loudness +(-23LUFS by default, unless modified through @var{target}). + More information about the Loudness Recommendation EBU R128 on @url{http://tech.ebu.ch/loudness}. diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index c74dac94da..688c7bf135 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -114,6 +114,8 @@ typedef struct EBUR128Context { int meter; ///< select a EBU mode between +9 and +18 int scale_range;///< the range of LU values according to the meter int y_zero_lu; ///< the y value (pixel position) for 0 LU +int y_opt_max; ///< the y value (pixel position) for 1 LU +int y_opt_min; ///< the y value (pixel position) for -1 LU int *y_line_ref;///< y reference values for drawing the LU lines in the graph and the gauge /* audio */ @@ -188,22 +190,31 @@ static const AVOption ebur128_options[] = { AVFILTER_DEFINE_CLASS(ebur128); static const uint8_t graph_colors[] = { -0xdd, 0x66, 0x66, // value above 0LU non reached -0x66, 0x66, 0xdd, // value below 0LU non reached -0x96, 0x33, 0x33, // value above 0LU reached -0x33, 0x33, 0x96, // value below 0LU reached -0xdd, 0x96, 0x96, // value above 0LU line non reached -0x96, 0x96, 0xdd, // value below 0LU line non reached -0xdd, 0x33, 0x33, // value above 0LU line reached -0x33, 0x33, 0xdd, // value below 0LU line reached +0xdd, 0x66, 0x66, // value above 1LU non reached below -1LU (impossible) +0x66, 0x66, 0xdd, // value below 1LU non reached below -1LU +0x96, 0x33, 0x33, // value above 1LU reached below -1LU (impossible) +0x33, 0x33, 0x96, // value below 1LU reached below -1LU +0xdd, 0x96, 0x96, // value above 1LU line non reached below -1LU (impossible) +0x96, 0x96, 0xdd, // value below 1LU line non reached below -1LU +0xdd, 0x33, 0x33, // value above 1LU line reached below -1LU (impossible) +0x33, 0x33, 0xdd, // value below 1LU line reached below -1LU +0xdd, 0x66, 0x66, // value above 1LU non reached above -1LU +0x66, 0xdd, 0x66, // value below 1LU non reached above -1LU +0x96, 0x33, 0x33, // value above 1LU reached above -1LU +0x33, 0x96, 0x33, // value below 1LU reached above -1LU +0xdd, 0x96, 0x96, // value above 1LU line non reached above -1LU +0x96, 0xdd, 0x96, // value below 1LU line non reached above -1LU +0xdd, 0x33, 0x33, // value above 1LU line reached above -1LU +0x33, 0xdd, 0x33, // value below 1LU line reached above -1LU }; static const uint8_t *get_graph_color(const EBUR128Context *ebur128, int v, int y) { -const int below0 = y > ebur128->y_zero_lu; +const int above_opt_max = y > ebur128->y_opt_max; +const int below_opt_min = y < ebur128->y_opt_min; const int reached = y >= v; const int line= ebur128->y_line_ref[y] || y == ebur128->y_zero_lu; -const int colorid = 4*line + 2*reached + below0; +const int colorid = 8*below_opt_min+ 4*line + 2*reached + above_opt_max; return graph_colors + 3*colorid; } @@ -337,6 +348,8 @@ static int config_video_output(AVFilterLink *outlink) /* draw graph */ ebur128->y_zero_lu = lu_to_y(ebur128, 0); +ebur128->y_opt_max = lu_to_y(ebur128, 1); +ebur128->y_opt_min = lu_to_y(ebur128, -1); p = outpicref->data[0] + ebur128->graph.y * outpicref->linesize[0] + ebur128->graph.x * 3; for (y = 0; y < ebur128->graph.h; y++) { -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 3/6] libavfilter/ebur128: add gauge option
Allow to show short-term instead of momentary in gauge. Useful for monitoring whilst live mixing. Signed-off-by: Daniel Molkentin Signed-off-by: Conrad Zelck --- doc/filters.texi| 9 - libavfilter/f_ebur128.c | 23 +-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 86ea25bda8..7f2baed9b5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -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, 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 -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 @url{http://tech.ebu.ch/loudness}. @@ -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 by EBU R128. However, material published online may prefer a level of -16LUFS (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 @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 89bfcb0b3e..c74dac94da 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -143,6 +143,7 @@ typedef struct EBUR128Context { 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 int target; ///< target level in LUFS used to set relative zero LU in visualization +int gauge_type; ///< whether gauge shows momentary or short } EBUR128Context; enum { @@ -151,6 +152,12 @@ enum { PEAK_MODE_TRUE_PEAKS= 1<<2, }; +enum { +GAUGE_TYPE_MOMENTARY = 0, +GAUGE_TYPE_SHORTTERM = 1, +}; + + #define OFFSET(x) offsetof(EBUR128Context, x) #define A AV_OPT_FLAG_AUDIO_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM @@ -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 }, { "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 }, +{ "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 }, }; @@ -741,9 +753,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) if (ebur128->do_video) { int x, y, ret; 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_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 */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; @@ -755,
Re: [FFmpeg-devel] [PATCH 0/6] Improvements for EBU R128 plugin (third round)
On 09.10.2018 14:32, Daniel Molkentin wrote: > Changes over second round: > > - gauge option: Add 'm' and 's' as alias parameter for >momentary and short-term > - fix spelling error in documentation > - remove "mabsolute" documentation which was added to the range >patch by accident > - fixed ranges for parameters > - bumped micro version for libavfilter Is there anything left to do until this can go in? Cheers, Daniel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel