[FFmpeg-devel] [PATCH 2/3] lavfi/ebur128: add metadata injection. - volnorm.patch (0/1)
Jan Ehrhardt
phpdev at ehrhardt.nl
Fri May 3 17:25:26 CEST 2013
Clément Bsch in gmane.comp.video.ffmpeg.devel (Fri, 3 May 2013
14:10:36 +0200):
>> volume has access to the frame pts, I don't think you need to use the
>> metadata for this.
>
>Note that you could also not check the adjustement value but the loudness
>value directly; basically if it's assumed to be silence (< 69), you just
>pass through.
OK, I simplified the patch to the one below.
Applied to the latest ffmpeg before
http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/163256
Because of this:
http://www.toolsforresearch.com/msecrash.gif
Jan
diff -u -r a/libavfilter/af_volume.c b/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c 2013-04-28 19:20:06.000000000 +0200
--- a/libavfilter/af_volume.c 2013-05-03 16:36:56.105388511 +0200
@@ -51,18 +51,24 @@
{ "fixed", "select 8-bit fixed-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED }, INT_MIN, INT_MAX, A|F, "precision" },
{ "float", "select 32-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT }, INT_MIN, INT_MAX, A|F, "precision" },
{ "double", "select 64-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A|F, "precision" },
+ { "metadata", "set the metadata key for loudness normalization", OFFSET(metadata), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = A|F },
{ NULL },
};
AVFILTER_DEFINE_CLASS(volume);
+static void set_fixed_volume(VolumeContext *vol, double volume)
+{
+ vol->volume_i = (int)(volume * 256 + 0.5);
+ vol->volume = vol->volume_i / 256.0;
+}
+
static av_cold int init(AVFilterContext *ctx)
{
VolumeContext *vol = ctx->priv;
if (vol->precision == PRECISION_FIXED) {
- vol->volume_i = (int)(vol->volume * 256 + 0.5);
- vol->volume = vol->volume_i / 256.0;
+ (vol, vol->volume);
av_log(ctx, AV_LOG_VERBOSE, "volume:(%d/256)(%f)(%1.2fdB) precision:fixed\n",
vol->volume_i, vol->volume, 20.0*log(vol->volume)/M_LN10);
} else {
@@ -171,13 +177,13 @@
switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
case AV_SAMPLE_FMT_U8:
- if (vol->volume_i < 0x1000000)
+ if (vol->volume_i < 0x1000000 && !vol->metadata)
vol->scale_samples = scale_samples_u8_small;
else
vol->scale_samples = scale_samples_u8;
break;
case AV_SAMPLE_FMT_S16:
- if (vol->volume_i < 0x10000)
+ if (vol->volume_i < 0x10000 && !vol->metadata)
vol->scale_samples = scale_samples_s16_small;
else
vol->scale_samples = scale_samples_s16;
@@ -216,11 +222,30 @@
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
{
- VolumeContext *vol = inlink->dst->priv;
- AVFilterLink *outlink = inlink->dst->outputs[0];
+ AVFilterContext *ctx = inlink->dst;
+ VolumeContext *vol = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
int nb_samples = buf->nb_samples;
AVFrame *out_buf;
+ if (vol->metadata) {
+ double loudness, new_volume, timestamp, mx;
+ AVDictionaryEntry *e;
+ mx = 20;
+ timestamp = (float)(1.0 * buf->pts / outlink->sample_rate);
+ mx = fmin(mx, timestamp);
+ e = av_dict_get(buf->metadata, vol->metadata, NULL, 0);
+ if (e) {
+ loudness = av_strtod(e->value, NULL);
+ if (loudness > -69) {
+ new_volume = fmax(-mx,fmin(mx,(-23 - loudness)));
+ av_log(NULL, AV_LOG_VERBOSE, "loudness=%f => %f => volume=%f\n",
+ loudness, new_volume, pow(10, new_volume / 20));
+ set_fixed_volume(vol, pow(10, new_volume / 20));
+ }
+ }
+ }
+
if (vol->volume == 1.0 || vol->volume_i == 256)
return ff_filter_frame(outlink, buf);
@@ -269,6 +294,12 @@
return ff_filter_frame(outlink, out_buf);
}
+static av_cold void uninit(AVFilterContext *ctx)
+{
+ VolumeContext *vol = ctx->priv;
+ av_opt_free(vol);
+}
+
static const AVFilterPad avfilter_af_volume_inputs[] = {
{
.name = "default",
@@ -294,6 +325,7 @@
.priv_size = sizeof(VolumeContext),
.priv_class = &volume_class,
.init = init,
+ .uninit = uninit,
.inputs = avfilter_af_volume_inputs,
.outputs = avfilter_af_volume_outputs,
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
diff -u -r a/libavfilter/af_volume.h b/libavfilter/af_volume.h
+++ b/libavfilter/af_volume.h 2013-04-28 19:20:06.000000000 +0200
--- a/libavfilter/af_volume.h 2013-05-03 15:14:13.231779601 +0200
@@ -48,6 +48,7 @@
void (*scale_samples)(uint8_t *dst, const uint8_t *src, int nb_samples,
int volume);
int samples_align;
+ char *metadata;
} VolumeContext;
void ff_volume_init_x86(VolumeContext *vol);
diff -u -r a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c
+++ b/libavfilter/f_ebur128.c 2013-04-28 19:20:06.000000000 +0200
--- a/libavfilter/f_ebur128.c 2013-05-03 16:01:17.460272087 +0200
@@ -1,3 +1,4 @@
+
/*
* Copyright (c) 2012 Clément Bsch
*
@@ -410,7 +411,7 @@
if (ebur128->loglevel != AV_LOG_INFO &&
ebur128->loglevel != AV_LOG_VERBOSE) {
- if (ebur128->do_video || ebur128->metadata)
+ if (ebur128->do_video)
ebur128->loglevel = AV_LOG_VERBOSE;
else
ebur128->loglevel = AV_LOG_INFO;
@@ -689,7 +690,7 @@
SET_META("LRA.high", ebur128->lra_high);
}
- av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT "\n",
+ av_log(ctx, AV_LOG_VERBOSE, "t: %-10s " LOG_FMT "\n",
av_ts2timestr(pts, &outlink->time_base),
loudness_400, loudness_3000,
ebur128->integrated_loudness, ebur128->loudness_range);
diff -u -r a/libavfilter/x86/af_volume_init.c b/libavfilter/x86/af_volume_init.c
+++ b/libavfilter/x86/af_volume_init.c 2013-04-28 19:20:06.000000000 +0200
--- a/libavfilter/x86/af_volume_init.c 2013-05-03 15:14:13.231779601 +0200
@@ -38,7 +38,7 @@
enum AVSampleFormat sample_fmt = av_get_packed_sample_fmt(vol->sample_fmt);
if (sample_fmt == AV_SAMPLE_FMT_S16) {
- if (EXTERNAL_SSE2(mm_flags) && vol->volume_i < 32768) {
+ if (EXTERNAL_SSE2(mm_flags) && vol->volume_i < 32768 && !vol->metadata) {
vol->scale_samples = ff_scale_samples_s16_sse2;
vol->samples_align = 8;
}
More information about the ffmpeg-devel
mailing list