[FFmpeg-devel] [PATCH 1/2] lavfi/ebur128: add metadata injection.
Clément Bœsch
ubitux at gmail.com
Fri Feb 22 00:22:39 CET 2013
---
doc/filters.texi | 5 +++++
libavfilter/f_ebur128.c | 29 +++++++++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/doc/filters.texi b/doc/filters.texi
index a93b433..9fbda34 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -6252,6 +6252,11 @@ Set the EBU scale meter. Default is @code{9}. Common values are @code{9} and
@code{18}, respectively for EBU scale meter +9 and EBU scale meter +18. Any
other integer value between this range is allowed.
+ at item metadata
+Set metadata injection. Default is @code{0}. If set to @code{1}, the audio will
+be divided into 100ms frames, each of them out of the filter containing various
+loudness information.
+
@end table
Example of real-time graph using @command{ffplay}, with a EBU scale meter +18:
diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c
index 66cc133..1d0513d 100644
--- a/libavfilter/f_ebur128.c
+++ b/libavfilter/f_ebur128.c
@@ -33,6 +33,7 @@
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
+#include "libavutil/dict.h"
#include "libavutil/xga_font_data.h"
#include "libavutil/opt.h"
#include "libavutil/timestamp.h"
@@ -90,6 +91,7 @@ struct rect { int x, y, w, h; };
typedef struct {
const AVClass *class; ///< AVClass context for log and options purpose
+ int metadata; ///< whether or not to inject loudness results in buffers
/* video */
int do_video; ///< 1 if video output enabled, 0 otherwise
@@ -133,6 +135,7 @@ static const AVOption ebur128_options[] = {
{ "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, V|F },
{ "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, V|F },
{ "meter", "set scale meter (+9 to +18)", OFFSET(meter), AV_OPT_TYPE_INT, {.i64 = 9}, 9, 18, V|F },
+ { "metadata", "inject metadata in the filtergraph", OFFSET(metadata), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, V|F },
{ NULL },
};
@@ -311,6 +314,20 @@ static int config_video_output(AVFilterLink *outlink)
return 0;
}
+static int config_audio_input(AVFilterLink *inlink)
+{
+ AVFilterContext *ctx = inlink->dst;
+ EBUR128Context *ebur128 = ctx->priv;
+
+ /* force 100ms framing in case of metadata injection: the frames must have
+ * a granularity of the window overlap to be accurately exploited */
+ if (ebur128->metadata)
+ inlink->min_samples =
+ inlink->max_samples =
+ inlink->partial_buf_size = inlink->sample_rate / 10;
+ return 0;
+}
+
static int config_audio_output(AVFilterLink *outlink)
{
int i;
@@ -648,6 +665,17 @@ static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *insamples)
"t: %-10s " LOG_FMT "\n", av_ts2timestr(pts, &outlink->time_base),
loudness_400, loudness_3000,
ebur128->integrated_loudness, ebur128->loudness_range);
+ if (ebur128->metadata) { /* happens only once per filter_frame call */
+ char metabuf[128];
+#define SET_META(name, var) do { \
+ snprintf(metabuf, sizeof(metabuf), "%6.1f", var); \
+ av_dict_set(&insamples->metadata, "lavfi.r128." name, metabuf, 0); \
+} while (0)
+ SET_META("L400", loudness_400);
+ SET_META("L3000", loudness_3000);
+ SET_META("I", ebur128->integrated_loudness);
+ SET_META("LRA", ebur128->loudness_range);
+ }
}
}
@@ -747,6 +775,7 @@ static const AVFilterPad ebur128_inputs[] = {
.type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = ff_null_get_audio_buffer,
.filter_frame = filter_frame,
+ .config_props = config_audio_input,
},
{ NULL }
};
--
1.8.1.4
More information about the ffmpeg-devel
mailing list