[FFmpeg-cvslog] avfilter/af_crystalizer: implement inverse filtering

Paul B Mahol git at videolan.org
Mon Dec 21 14:16:26 EET 2020


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Dec 21 13:07:23 2020 +0100| [204a90643713b03003b4d818dbc9dddddbd465bd] | committer: Paul B Mahol

avfilter/af_crystalizer: implement inverse filtering

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=204a90643713b03003b4d818dbc9dddddbd465bd
---

 doc/filters.texi             |   3 +-
 libavfilter/af_crystalizer.c | 169 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 163 insertions(+), 9 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 2589ff4349..d6a53624ee 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -3690,8 +3690,9 @@ The filter accepts the following options:
 
 @table @option
 @item i
-Sets the intensity of effect (default: 2.0). Must be in range between 0.0
+Sets the intensity of effect (default: 2.0). Must be in range between -10.0 to 0
 (unchanged sound) to 10.0 (maximum effect).
+To inverse filtering use negative value.
 
 @item c
 Enable clipping. By default is enabled.
diff --git a/libavfilter/af_crystalizer.c b/libavfilter/af_crystalizer.c
index 5f7bce0a8c..d1f44984ac 100644
--- a/libavfilter/af_crystalizer.c
+++ b/libavfilter/af_crystalizer.c
@@ -36,7 +36,7 @@ typedef struct CrystalizerContext {
 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
 
 static const AVOption crystalizer_options[] = {
-    { "i", "set intensity",    OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0}, 0, 10, A },
+    { "i", "set intensity",    OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0},-10, 10, A },
     { "c", "enable clipping",  OFFSET(clip), AV_OPT_TYPE_BOOL,  {.i64=1},   0,  1, A },
     { NULL }
 };
@@ -91,7 +91,7 @@ static int filter_flt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
     const void **s = td->s;
     const int nb_samples = td->nb_samples;
     const int channels = td->channels;
-    float mult = td->mult;
+    const float mult = td->mult;
     const int clip = td->clip;
     const int start = (channels * jobnr) / nb_jobs;
     const int end = (channels * (jobnr+1)) / nb_jobs;
@@ -195,7 +195,7 @@ static int filter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
     const void **s = td->s;
     const int nb_samples = td->nb_samples;
     const int channels = td->channels;
-    double mult = td->mult;
+    const double mult = td->mult;
     const int clip = td->clip;
     const int start = (channels * jobnr) / nb_jobs;
     const int end = (channels * (jobnr+1)) / nb_jobs;
@@ -220,16 +220,157 @@ static int filter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
     return 0;
 }
 
+static int ifilter_flt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    ThreadData *td = arg;
+    void **d = td->d;
+    void **p = td->p;
+    const void **s = td->s;
+    const int nb_samples = td->nb_samples;
+    const int channels = td->channels;
+    const float mult = -td->mult;
+    const float div = -td->mult + 1.f;
+    const int clip = td->clip;
+    const int start = (channels * jobnr) / nb_jobs;
+    const int end = (channels * (jobnr+1)) / nb_jobs;
+    float *prv = p[0];
+    int n, c;
+
+    for (c = start; c < end; c++) {
+        const float *src = s[0];
+        float *dst = d[0];
+
+        for (n = 0; n < nb_samples; n++) {
+            float current = src[c];
+            dst[c] = (current + prv[c] * mult) / div;
+            prv[c] = dst[c];
+            if (clip) {
+                dst[c] = av_clipf(dst[c], -1, 1);
+            }
+
+            dst += channels;
+            src += channels;
+        }
+    }
+
+    return 0;
+}
+
+static int ifilter_dbl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    ThreadData *td = arg;
+    void **d = td->d;
+    void **p = td->p;
+    const void **s = td->s;
+    const int nb_samples = td->nb_samples;
+    const int channels = td->channels;
+    const double mult = -td->mult;
+    const double div = -td->mult + 1.f;
+    const int clip = td->clip;
+    const int start = (channels * jobnr) / nb_jobs;
+    const int end = (channels * (jobnr+1)) / nb_jobs;
+    double *prv = p[0];
+    int n, c;
+
+    for (c = start; c < end; c++) {
+        const double *src = s[0];
+        double *dst = d[0];
+
+        for (n = 0; n < nb_samples; n++) {
+            double current = src[c];
+
+            dst[c] = (current + prv[c] * mult) / div;
+            prv[c] = dst[c];
+            if (clip) {
+                dst[c] = av_clipd(dst[c], -1, 1);
+            }
+
+            dst += channels;
+            src += channels;
+        }
+    }
+
+    return 0;
+}
+
+static int ifilter_fltp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    ThreadData *td = arg;
+    void **d = td->d;
+    void **p = td->p;
+    const void **s = td->s;
+    const int nb_samples = td->nb_samples;
+    const int channels = td->channels;
+    const float mult = -td->mult;
+    const float div = -td->mult + 1.f;
+    const int clip = td->clip;
+    const int start = (channels * jobnr) / nb_jobs;
+    const int end = (channels * (jobnr+1)) / nb_jobs;
+    int n, c;
+
+    for (c = start; c < end; c++) {
+        const float *src = s[c];
+        float *dst = d[c];
+        float *prv = p[c];
+
+        for (n = 0; n < nb_samples; n++) {
+            float current = src[n];
+
+            dst[n] = (current + prv[0] * mult) / div;
+            prv[0] = dst[n];
+            if (clip) {
+                dst[n] = av_clipf(dst[n], -1, 1);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int ifilter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    ThreadData *td = arg;
+    void **d = td->d;
+    void **p = td->p;
+    const void **s = td->s;
+    const int nb_samples = td->nb_samples;
+    const int channels = td->channels;
+    const double mult = -td->mult;
+    const double div = -td->mult + 1.f;
+    const int clip = td->clip;
+    const int start = (channels * jobnr) / nb_jobs;
+    const int end = (channels * (jobnr+1)) / nb_jobs;
+    int n, c;
+
+    for (c = start; c < end; c++) {
+        const double *src = s[c];
+        double *dst = d[c];
+        double *prv = p[c];
+
+        for (n = 0; n < nb_samples; n++) {
+            double current = src[n];
+
+            dst[n] = (current + prv[0] * mult) / div;
+            prv[0] = dst[n];
+            if (clip) {
+                dst[n] = av_clipd(dst[n], -1, 1);
+            }
+        }
+    }
+
+    return 0;
+}
+
 static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
     CrystalizerContext *s = ctx->priv;
 
     switch (inlink->format) {
-    case AV_SAMPLE_FMT_FLT:  s->filter = filter_flt;  break;
-    case AV_SAMPLE_FMT_DBL:  s->filter = filter_dbl;  break;
-    case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break;
-    case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break;
+    case AV_SAMPLE_FMT_FLT:  s->filter = s->mult >= 0.f ? filter_flt  : ifilter_flt;  break;
+    case AV_SAMPLE_FMT_DBL:  s->filter = s->mult >= 0.f ? filter_dbl  : ifilter_dbl;  break;
+    case AV_SAMPLE_FMT_FLTP: s->filter = s->mult >= 0.f ? filter_fltp : ifilter_fltp; break;
+    case AV_SAMPLE_FMT_DBLP: s->filter = s->mult >= 0.f ? filter_dblp : ifilter_dblp; break;
     }
 
     return 0;
@@ -285,6 +426,18 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_frame_free(&s->prev);
 }
 
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    int ret;
+
+    ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
+    if (ret < 0)
+        return ret;
+
+    return config_input(ctx->inputs[0]);
+}
+
 static const AVFilterPad inputs[] = {
     {
         .name         = "default",
@@ -312,7 +465,7 @@ AVFilter ff_af_crystalizer = {
     .uninit         = uninit,
     .inputs         = inputs,
     .outputs        = outputs,
-    .process_command = ff_filter_process_command,
+    .process_command = process_command,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                       AVFILTER_FLAG_SLICE_THREADS,
 };



More information about the ffmpeg-cvslog mailing list