[FFmpeg-cvslog] avfilter/avf_showcwt: add bar display support

Paul B Mahol git at videolan.org
Thu Jul 13 01:07:10 EEST 2023


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Jul 10 22:52:04 2023 +0200| [422bfdc4aefc9117a9aa9611269ba666c91b497c] | committer: Paul B Mahol

avfilter/avf_showcwt: add bar display support

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

 libavfilter/avf_showcwt.c | 126 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 111 insertions(+), 15 deletions(-)

diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c
index 896e470dd1..61b04bf840 100644
--- a/libavfilter/avf_showcwt.c
+++ b/libavfilter/avf_showcwt.c
@@ -96,6 +96,7 @@ typedef struct ShowCWTContext {
     AVFrame *ifft_in;
     AVFrame *ifft_out;
     AVFrame *ch_out;
+    AVFrame *bh_out;
     int nb_threads;
     int nb_channels;
     int nb_consumed_samples;
@@ -118,6 +119,8 @@ typedef struct ShowCWTContext {
     float minimum_frequency;
     float maximum_frequency;
     float deviation;
+    float bar_ratio;
+    int bar_size;
 
     AVFloatDSPContext *fdsp;
 } ShowCWTContext;
@@ -159,6 +162,7 @@ static const AVOption showcwt_options[] = {
     {  "rl", "right to left", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_RL}, 0, 0, FLAGS, "direction" },
     {  "ud", "up to down",    0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_UD}, 0, 0, FLAGS, "direction" },
     {  "du", "down to up",    0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_DU}, 0, 0, FLAGS, "direction" },
+    { "bar", "set bar ratio", OFFSET(bar_ratio), AV_OPT_TYPE_FLOAT, {.dbl = 0.}, 0, 1, FLAGS },
     { NULL }
 };
 
@@ -184,6 +188,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_frame_free(&s->ifft_in);
     av_frame_free(&s->ifft_out);
     av_frame_free(&s->ch_out);
+    av_frame_free(&s->bh_out);
 
     if (s->fft) {
         for (int n = 0; n < s->nb_threads; n++)
@@ -315,6 +320,80 @@ static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, i
     return 0;
 }
 
+#define DRAW_BAR_COLOR(x) \
+do { \
+    if (Y <= ht) { \
+        dstY[x] = 0; \
+        dstU[x] = 128; \
+        dstV[x] = 128; \
+    } else { \
+        float mul = (Y - ht) * bh[0]; \
+        dstY[x] = av_clip_uint8(lrintf(Y * mul * 255.f)); \
+        dstU[x] = av_clip_uint8(lrintf((U-0.5f) * 128.f + 128)); \
+        dstV[x] = av_clip_uint8(lrintf((V-0.5f) * 128.f + 128)); \
+    } \
+} while (0)
+
+static void draw_bar(ShowCWTContext *s, int y,
+                     float Y, float U, float V)
+{
+    float *bh = ((float *)s->bh_out->extended_data[0]) + y;
+    const ptrdiff_t ylinesize = s->outpicref->linesize[0];
+    const ptrdiff_t ulinesize = s->outpicref->linesize[1];
+    const ptrdiff_t vlinesize = s->outpicref->linesize[2];
+    const int direction = s->direction;
+    const int bar_size = s->bar_size;
+    const float rcp_bar_h = 1.f / bar_size;
+    uint8_t *dstY, *dstU, *dstV;
+    const int w_1 = s->w - 1;
+
+    bh[0] = 1.f / (Y + 0.0001f);
+    switch (direction) {
+        case DIRECTION_LR:
+            dstY = s->outpicref->data[0] + y * ylinesize;
+            dstU = s->outpicref->data[1] + y * ulinesize;
+            dstV = s->outpicref->data[2] + y * vlinesize;
+            for (int x = 0; x < bar_size; x++) {
+                float ht = (bar_size - x) * rcp_bar_h;
+                DRAW_BAR_COLOR(x);
+            }
+            break;
+        case DIRECTION_RL:
+            dstY = s->outpicref->data[0] + y * ylinesize;
+            dstU = s->outpicref->data[1] + y * ulinesize;
+            dstV = s->outpicref->data[2] + y * vlinesize;
+            for (int x = 0; x < bar_size; x++) {
+                float ht = x * rcp_bar_h;
+                DRAW_BAR_COLOR(w_1 - bar_size + x);
+            }
+            break;
+        case DIRECTION_UD:
+            dstY = s->outpicref->data[0] + w_1 - y;
+            dstU = s->outpicref->data[1] + w_1 - y;
+            dstV = s->outpicref->data[2] + w_1 - y;
+            for (int x = 0; x < bar_size; x++) {
+                float ht = (bar_size - x) * rcp_bar_h;
+                DRAW_BAR_COLOR(0);
+                dstY += ylinesize;
+                dstU += ulinesize;
+                dstV += vlinesize;
+            }
+            break;
+        case DIRECTION_DU:
+            dstY = s->outpicref->data[0] + w_1 - y + ylinesize * (s->h - 1 - bar_size);
+            dstU = s->outpicref->data[1] + w_1 - y + ulinesize * (s->h - 1 - bar_size);
+            dstV = s->outpicref->data[2] + w_1 - y + vlinesize * (s->h - 1 - bar_size);
+            for (int x = 0; x < bar_size; x++) {
+                float ht = x * rcp_bar_h;
+                DRAW_BAR_COLOR(0);
+                dstY += ylinesize;
+                dstU += ulinesize;
+                dstV += vlinesize;
+            }
+            break;
+    }
+}
+
 static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ShowCWTContext *s = ctx->priv;
@@ -330,6 +409,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
     const int ihop_size = s->ihop_size;
     const int direction = s->direction;
     uint8_t *dstY, *dstU, *dstV, *dstA;
+    const int bar_size = s->bar_size;
     const int mode = s->mode;
     const int w_1 = s->w - 1;
     const int x = s->pos;
@@ -414,6 +494,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
                 dstV[0] = av_clip_uint8(lrintf(V * 255.f));
                 if (dstA)
                     dstA[0] = dstY[0];
+
+                if (bar_size > 0)
+                    draw_bar(s, y, Y, U, V);
             }
             break;
         case 3:
@@ -441,6 +524,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
                 dstV[0] = av_clip_uint8(lrintf(V * 255.f));
                 if (dstA)
                     dstA[0] = dstY[0];
+
+                if (bar_size > 0)
+                    draw_bar(s, y, Y, U, V);
             }
             break;
         case 2:
@@ -455,6 +541,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
             dstV[0] = av_clip_uint8(lrintf(V * 255.f));
             if (dstA)
                 dstA[0] = dstY[0];
+            if (bar_size > 0)
+                draw_bar(s, y, Y, U, V);
             break;
         case 1:
             Y = atan2f(src[0].im, src[0].re);
@@ -463,6 +551,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
             dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
             if (dstA)
                 dstA[0] = dstY[0];
+            if (bar_size > 0)
+                draw_bar(s, y, Y, 0.5f, 0.5f);
             break;
         case 0:
             Y = hypotf(src[0].re, src[0].im);
@@ -471,6 +561,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
             dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
             if (dstA)
                 dstA[0] = dstY[0];
+
+            if (bar_size > 0)
+                draw_bar(s, y, Y, 0.5f, 0.5f);
             break;
         }
     }
@@ -589,10 +682,12 @@ static int config_output(AVFilterLink *outlink)
     switch (s->direction) {
     case DIRECTION_LR:
     case DIRECTION_RL:
+        s->bar_size = s->w * s->bar_ratio;
         s->frequency_band_count = s->h;
         break;
     case DIRECTION_UD:
     case DIRECTION_DU:
+        s->bar_size = s->h * s->bar_ratio;
         s->frequency_band_count = s->w;
         break;
     }
@@ -651,6 +746,7 @@ static int config_output(AVFilterLink *outlink)
     s->kernel_x = av_frame_alloc();
     s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);
     s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
+    s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count);
     s->ifft_in = av_frame_alloc();
     s->ifft_out = av_frame_alloc();
     s->kernel = av_frame_alloc();
@@ -658,8 +754,8 @@ static int config_output(AVFilterLink *outlink)
     s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));
     s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));
     if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x ||
-        !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop ||
-        !s->frequency_band || !s->kernel || !s->cache || !s->index)
+        !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out ||
+        !s->frequency_band || !s->kernel || !s->cache || !s->index || !s->bh_out)
         return AVERROR(ENOMEM);
 
     s->ifft_in->format     = inlink->format;
@@ -760,16 +856,16 @@ static int config_output(AVFilterLink *outlink)
 
     switch (s->direction) {
     case DIRECTION_LR:
-        s->pos = 0;
+        s->pos = s->bar_size;
         break;
     case DIRECTION_RL:
-        s->pos = s->w - 1;
+        s->pos = FFMAX(0, s->w - 2 - s->bar_size);
         break;
     case DIRECTION_UD:
-        s->pos = 0;
+        s->pos = s->bar_size;
         break;
     case DIRECTION_DU:
-        s->pos = s->h - 1;
+        s->pos = FFMAX(0, s->h - 2 - s->bar_size);
         break;
     }
 
@@ -802,7 +898,7 @@ static int output_frame(AVFilterContext *ctx)
             for (int p = 0; p < nb_planes; p++) {
                 ptrdiff_t linesize = s->outpicref->linesize[p];
 
-                for (int y = s->h - 1; y > 0; y--) {
+                for (int y = s->h - 1; y > s->bar_size; y--) {
                     uint8_t *dst = s->outpicref->data[p] + y * linesize;
 
                     memmove(dst, dst - linesize, s->w);
@@ -813,7 +909,7 @@ static int output_frame(AVFilterContext *ctx)
             for (int p = 0; p < nb_planes; p++) {
                 ptrdiff_t linesize = s->outpicref->linesize[p];
 
-                for (int y = 0; y < s->h - 1; y++) {
+                for (int y = 0; y < s->h - 2 - s->bar_size; y++) {
                     uint8_t *dst = s->outpicref->data[p] + y * linesize;
 
                     memmove(dst, dst + linesize, s->w);
@@ -833,28 +929,28 @@ static int output_frame(AVFilterContext *ctx)
         case DIRECTION_LR:
             s->pos++;
             if (s->pos >= s->w) {
-                s->pos = 0;
+                s->pos = s->bar_size;
                 s->new_frame = 1;
             }
             break;
         case DIRECTION_RL:
             s->pos--;
             if (s->pos < 0) {
-                s->pos = s->w - 1;
+                s->pos = FFMAX(0, s->w - 2 - s->bar_size);
                 s->new_frame = 1;
             }
             break;
         case DIRECTION_UD:
             s->pos++;
             if (s->pos >= s->h) {
-                s->pos = 0;
+                s->pos = s->bar_size;
                 s->new_frame = 1;
             }
             break;
         case DIRECTION_DU:
             s->pos--;
             if (s->pos < 0) {
-                s->pos = s->h - 1;
+                s->pos = FFMAX(0, s->h - 2 - s->bar_size);
                 s->new_frame = 1;
             }
             break;
@@ -864,13 +960,13 @@ static int output_frame(AVFilterContext *ctx)
         switch (s->direction) {
         case DIRECTION_UD:
         case DIRECTION_LR:
-            s->pos = 0;
+            s->pos = s->bar_size;
             break;
         case DIRECTION_RL:
-            s->pos = s->w - 1;
+            s->pos = FFMAX(0, s->w - 2 - s->bar_size);
             break;
         case DIRECTION_DU:
-            s->pos = s->h - 1;
+            s->pos = FFMAX(0, s->h - 2 - s->bar_size);
             break;
         }
         break;



More information about the ffmpeg-cvslog mailing list