[FFmpeg-cvslog] avfilter/avf_showfreqs: add option to draw subset of channels

Paul B Mahol git at videolan.org
Fri Apr 22 02:23:59 EEST 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Thu Apr 21 17:44:06 2022 +0200| [0b6e801d4ae176fc5fff5173f226ee7b400de3fe] | committer: Paul B Mahol

avfilter/avf_showfreqs: add option to draw subset of channels

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

 doc/filters.texi            |  3 +++
 libavfilter/avf_showfreqs.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 605d92a952..79cabcfd6c 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -28432,6 +28432,9 @@ It accepts the following values:
 @item delay
 @end table
 Default is @code{magnitude}.
+
+ at item channels
+Set channels to use when processing audio. By default all are processed.
 @end table
 
 @section showspatial
diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c
index b2c7886985..5d13f71a2b 100644
--- a/libavfilter/avf_showfreqs.c
+++ b/libavfilter/avf_showfreqs.c
@@ -51,6 +51,9 @@ typedef struct ShowFreqsContext {
     int ascale, fscale;
     int avg;
     int win_func;
+    char *ch_layout_str;
+    uint8_t *bypass;
+    AVChannelLayout ch_layout;
     AVTXContext *fft;
     av_tx_fn tx_fn;
     AVComplexFloat **fft_input;
@@ -62,6 +65,7 @@ typedef struct ShowFreqsContext {
     float minamp;
     int hop_size;
     int nb_channels;
+    int nb_draw_channels;
     int nb_freq;
     int win_size;
     float scale;
@@ -100,6 +104,7 @@ static const AVOption showfreqs_options[] = {
         { "magnitude", "show magnitude",  0, AV_OPT_TYPE_CONST, {.i64=MAGNITUDE}, 0, 0, FLAGS, "data" },
         { "phase",     "show phase",      0, AV_OPT_TYPE_CONST, {.i64=PHASE},     0, 0, FLAGS, "data" },
         { "delay",     "show group delay",0, AV_OPT_TYPE_CONST, {.i64=DELAY},     0, 0, FLAGS, "data" },
+    { "channels", "set channels to draw", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS },
     { NULL }
 };
 
@@ -162,11 +167,15 @@ static int config_output(AVFilterLink *outlink)
         av_freep(&s->fft_data[i]);
         av_freep(&s->avg_data[i]);
     }
+    av_freep(&s->bypass);
     av_freep(&s->fft_input);
     av_freep(&s->fft_data);
     av_freep(&s->avg_data);
     s->nb_channels = inlink->ch_layout.nb_channels;
 
+    s->bypass = av_calloc(s->nb_channels, sizeof(*s->bypass));
+    if (!s->bypass)
+        return AVERROR(ENOMEM);
     s->fft_input = av_calloc(s->nb_channels, sizeof(*s->fft_input));
     if (!s->fft_input)
         return AVERROR(ENOMEM);
@@ -212,6 +221,26 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = s->w;
     outlink->h = s->h;
 
+    ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout);
+    if (ret < 0)
+        return ret;
+    s->nb_draw_channels = s->nb_channels;
+
+    if (strcmp(s->ch_layout_str, "all")) {
+        int nb_draw_channels = 0;
+        av_channel_layout_from_string(&s->ch_layout,
+                                      s->ch_layout_str);
+
+        for (int ch = 0; ch < s->nb_channels; ch++) {
+            const enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch);
+
+            s->bypass[ch] = av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0;
+            nb_draw_channels += s->bypass[ch] == 0;
+        }
+
+        s->nb_draw_channels = nb_draw_channels;
+    }
+
     return 0;
 }
 
@@ -288,8 +317,8 @@ static inline void plot_freq(ShowFreqsContext *s, int ch,
         y = a * outlink->h - 1;
         break;
     case SEPARATE:
-        end = (outlink->h / s->nb_channels) * (ch + 1);
-        y = (outlink->h / s->nb_channels) * ch + a * (outlink->h / s->nb_channels) - 1;
+        end = (outlink->h / s->nb_draw_channels) * (ch + 1);
+        y = (outlink->h / s->nb_draw_channels) * ch + a * (outlink->h / s->nb_draw_channels) - 1;
         break;
     default:
         av_assert0(0);
@@ -361,6 +390,9 @@ static int plot_freqs(AVFilterLink *inlink, int64_t pts)
     for (ch = 0; ch < s->nb_channels; ch++) {
         const float *p = (float *)in->extended_data[ch];
 
+        if (s->bypass[ch])
+            continue;
+
         for (n = 0; n < win_size; n++) {
             s->fft_input[ch][n].re = p[n] * s->window_func_lut[n];
             s->fft_input[ch][n].im = 0;
@@ -369,6 +401,9 @@ static int plot_freqs(AVFilterLink *inlink, int64_t pts)
 
     /* run FFT on each samples set */
     for (ch = 0; ch < s->nb_channels; ch++) {
+        if (s->bypass[ch])
+            continue;
+
         s->tx_fn(s->fft, s->fft_data[ch], s->fft_input[ch], sizeof(float));
     }
 
@@ -392,6 +427,9 @@ static int plot_freqs(AVFilterLink *inlink, int64_t pts)
         if (color)
             av_parse_color(fg, color, -1, ctx);
 
+        if (s->bypass[ch])
+            continue;
+
         switch (s->data_mode) {
         case MAGNITUDE:
             a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1);
@@ -482,6 +520,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     ShowFreqsContext *s = ctx->priv;
     int i;
 
+    av_channel_layout_uninit(&s->ch_layout);
     av_tx_uninit(&s->fft);
     for (i = 0; i < s->nb_channels; i++) {
         if (s->fft_input)
@@ -491,6 +530,7 @@ static av_cold void uninit(AVFilterContext *ctx)
         if (s->avg_data)
             av_freep(&s->avg_data[i]);
     }
+    av_freep(&s->bypass);
     av_freep(&s->fft_input);
     av_freep(&s->fft_data);
     av_freep(&s->avg_data);



More information about the ffmpeg-cvslog mailing list