[FFmpeg-devel] [RFC][WIP][PATCH] avfilter: add ITU-R 468-4 noise meter

Paul B Mahol onemda at gmail.com
Mon Dec 7 00:17:41 CET 2015


On 12/6/15, Ganesh Ajjanagadde <gajjanag at mit.edu> wrote:
> On Sun, Dec 6, 2015 at 3:58 PM, Paul B Mahol <onemda at gmail.com> wrote:
>> Signed-off-by: Paul B Mahol <onemda at gmail.com>
>> ---
>>  libavfilter/Makefile     |   1 +
>>  libavfilter/af_itur468.c | 223
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>  libavfilter/allfilters.c |   1 +
>>  3 files changed, 225 insertions(+)
>>  create mode 100644 libavfilter/af_itur468.c
>>
>> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
>> index 8884d1d..2a053d0 100644
>> --- a/libavfilter/Makefile
>> +++ b/libavfilter/Makefile
>> @@ -76,6 +76,7 @@ OBJS-$(CONFIG_EQUALIZER_FILTER)              +=
>> af_biquads.o
>>  OBJS-$(CONFIG_EXTRASTEREO_FILTER)            += af_extrastereo.o
>>  OBJS-$(CONFIG_FLANGER_FILTER)                += af_flanger.o
>> generate_wave_table.o
>>  OBJS-$(CONFIG_HIGHPASS_FILTER)               += af_biquads.o
>> +OBJS-$(CONFIG_ITUR468_FILTER)                += af_itur468.o
>>  OBJS-$(CONFIG_JOIN_FILTER)                   += af_join.o
>>  OBJS-$(CONFIG_LADSPA_FILTER)                 += af_ladspa.o
>>  OBJS-$(CONFIG_LOWPASS_FILTER)                += af_biquads.o
>> diff --git a/libavfilter/af_itur468.c b/libavfilter/af_itur468.c
>> new file mode 100644
>> index 0000000..9b0eddc
>> --- /dev/null
>> +++ b/libavfilter/af_itur468.c
>> @@ -0,0 +1,223 @@
>> +/*
>> + * Copyright (c) 2010 Fons Adriaensen <fons at kokkinizita.net>
>> + *
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * FFmpeg is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> along
>> + * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> + */
>> +
>> +#include <float.h>
>> +#include <math.h>
>> +
>> +#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 "audio.h"
>> +#include "avfilter.h"
>> +#include "formats.h"
>> +#include "internal.h"
>> +
>> +typedef struct ITUR468Filter {
>> +    double whp;
>> +    double a11, a12;
>> +    double a21, a22;
>> +    double a31, a32;
>> +    double b30, b31, b32;
>> +    double zhp;
>> +    double z11, z12;
>> +    double z21, z22;
>> +    double z31, z32;
>> +
>> +    double a1, b1;
>> +    double a2, b2;
>> +    double z1, z2;
>> +} ITUR468Filter;
>> +
>> +typedef struct {
>> +    const AVClass *class;
>> +
>> +    ITUR468Filter *filter;
>> +} ITUR468Context;
>> +
>> +static int config_output(AVFilterLink *outlink)
>> +{
>> +    AVFilterContext *ctx = outlink->src;
>> +    AVFilterLink *inlink = ctx->inputs[0];
>> +    ITUR468Context *s = ctx->priv;
>> +    int c;
>> +
>> +    s->filter = av_calloc(inlink->channels, sizeof(*s->filter));
>> +    if (!s->filter)
>> +        return AVERROR(ENOMEM);
>> +
>> +    for (c = 0; c < inlink->channels; c++) {
>> +        ITUR468Filter *f = &s->filter[c];
>> +
>> +        f->whp =  3.8715217e-01;
>> +        f->a11 = -8.4163201e-01;
>> +        f->a12 =  3.0498350e-01;
>> +        f->a21 = -6.5680242e-01;
>> +        f->a22 =  2.3733993e-01;
>> +        f->a31 = -3.3843556e-01;
>> +        f->a32 =  4.3756709e-01;
>> +        f->b30 =  9.8607997e-01;
>> +        f->b31 =  5.4846389e-01;
>> +        f->b32 = -8.2465158e-02;
>> +        f->a1  = 670. / inlink->sample_rate;
>> +        f->b1  = 3.5  / inlink->sample_rate;
>> +        f->a2  = 6.6  / inlink->sample_rate;
>> +        f->b2  = 0.65 / inlink->sample_rate;
>
> Please add a comment with a link: where do these "magic" numbers come from?
>
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int filter_frame(AVFilterLink *inlink, AVFrame *in)
>> +{
>> +    AVFilterContext *ctx = inlink->dst;
>> +    ITUR468Context *s = ctx->priv;
>> +    AVDictionary **metadata;
>> +    metadata = avpriv_frame_get_metadatap(in);
>> +    int n, c;
>> +
>> +    for (c = 0; c < inlink->channels; c++) {
>> +        ITUR468Filter *f = &s->filter[c];
>> +        double *src = (double *)in->extended_data[c];
>> +        double out, x, zhp, z11, z12, z21, z22, z31, z32, z1, z2;
>> +
>> +        zhp = f->zhp;
>> +        z11 = f->z11;
>> +        z12 = f->z12;
>> +        z21 = f->z21;
>> +        z22 = f->z22;
>> +        z31 = f->z31;
>> +        z32 = f->z32;
>> +        z1  = f->z1;
>> +        z2  = f->z2;
>> +
>> +        for (n = 0; n < in->nb_samples; n++) {
>> +            x = src[n];
>> +            zhp += f->whp * (x - zhp) + 1e-20;
>> +            x -= zhp;
>> +            x -= f->a11 * z11 + f->a12 * z12;
>> +            z12 = z11;
>> +            z11 = x;
>> +            x -= f->a21 * z21 + f->a22 * z22;
>> +            z22 = z21;
>> +            z21 = x;
>> +            x -= f->a31 * z31 + f->a32 * z32;
>> +            out = f->b30 * x + f->b31 * z31 + f->b32 * z32;
>> +            z32 = z31;
>> +            z31 = x;
>> +            x = out;
>> +            x = fabs(x) + 1e-30;
>
> All this 1e-20, 1e-30: is is needed for well-conditioning the output
> or what? A lot of the questions I ask can simply be clarified by
> adding a one-liner link to the actual source of this filter, which for
> some obscure reason you seem to not do.
> How can you expect the reviewer to know the significance of all these
> magic numbers?

It is from obscure jnoisemeter utility, there is even ladspa plugin
for it (bobdsp)

Search for ITU-R 468 for more info.

>
> With the information you provide, all I can do is say "whatever,
> another filter obtained from somewhere on the internet that is being
> imported into FFmpeg".
>
>> +            z1 -= z1 * f->b1;
>> +            if (x > z1)
>> +                z1 += f->a1 * (x - z1);
>> +
>> +            z2 -= z2 * f->b2;
>> +            if (z1 > z2)
>> +                z2 += f->a2 * (z1 - z2);
>> +        }
>> +
>> +        f->zhp = zhp;
>> +        f->z11 = z11;
>> +        f->z12 = z12;
>> +        f->z21 = z21;
>> +        f->z22 = z22;
>> +        f->z31 = z31;
>> +        f->z32 = z32;
>> +        f->z1 = z1;
>> +        f->z2 = z2;
>> +        if (metadata) {
>> +            uint8_t value[128];
>> +            uint8_t key[128];
>> +
>> +            snprintf(key, sizeof(key), "lavfi.itur468.%d.noise", c + 1);
>> +            snprintf(value, sizeof(value), "%f", 1.1453 * f->z2);
>> +            av_dict_set(metadata, key, value, 0);
>> +        }
>> +    }
>> +
>> +    return ff_filter_frame(ctx->outputs[0], in);
>> +}
>> +
>> +static int query_formats(AVFilterContext *ctx)
>> +{
>> +    AVFilterFormats *formats;
>> +    AVFilterChannelLayouts *layouts;
>> +    AVFilterLink *inlink = ctx->inputs[0];
>> +    AVFilterLink *outlink = ctx->outputs[0];
>> +    int ret;
>> +
>> +    static const enum AVSampleFormat sample_fmts[] = {
>> AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE };
>> +    static const int input_srate[] = {48000, -1};
>> +
>> +    formats = ff_make_format_list(sample_fmts);
>> +    if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0 ||
>> +        (ret = ff_formats_ref(formats, &outlink->in_formats)) < 0)
>> +        return ret;
>> +
>> +    layouts = ff_all_channel_counts();
>> +    if ((ret = ff_channel_layouts_ref(layouts,
>> &inlink->out_channel_layouts)) < 0 ||
>> +        (ret = ff_channel_layouts_ref(layouts,
>> &outlink->in_channel_layouts)) < 0)
>> +        return ret;
>> +
>> +    formats = ff_make_format_list(input_srate);
>> +    if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0 ||
>> +        (ret = ff_formats_ref(formats, &outlink->in_samplerates)) < 0)
>> +        return ret;
>
> Still leaky, I hope you recognize it.
>
> I have provided illustrations for easily resolving this, see the CID
> patchset.
>
> By the way, what is the RFC/WIP for: FFmpeg seems to basically accept
> any filter under the sun, regardless of importance/utility/review
> status?
> I have no idea.
>
> On a positive note: thanks for doing real arithmetic.
>
> [...]
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list