[FFmpeg-cvslog] avfilter/avf_showspectrum: add alpha pixel format support

Paul B Mahol git at videolan.org
Thu Apr 14 18:28:09 EEST 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Thu Apr 14 17:26:13 2022 +0200| [1764a6887befc11eca91d2f4240e4b0233afc246] | committer: Paul B Mahol

avfilter/avf_showspectrum: add alpha pixel format support

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

 doc/filters.texi               |   8 +++-
 libavfilter/avf_showspectrum.c | 101 ++++++++++++++++++++++++++++++++---------
 2 files changed, 86 insertions(+), 23 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index c04537e2d6..5fae4424e6 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -2562,7 +2562,7 @@ Output only difference samples, useful to hear introduced distortions.
 By default is disabled.
 
 @item adaptive
-Set strenght of adaptive distortion applied. Default value is 0.5.
+Set strength of adaptive distortion applied. Default value is 0.5.
 Allowed range is from 0 to 1.
 
 @item iterations
@@ -28611,6 +28611,9 @@ Allowed range is from 10 to 200.
 @item limit
 Set upper limit of input audio samples volume in dBFS. Default is 0 dBFS.
 Allowed range is from -100 to 100.
+
+ at item opacity
+Set opacity strength when using pixel format output with alpha component.
 @end table
 
 The usage is very similar to the showwaves filter; see the examples in that
@@ -28792,6 +28795,9 @@ Allowed range is from 10 to 200.
 @item limit
 Set upper limit of input audio samples volume in dBFS. Default is 0 dBFS.
 Allowed range is from -100 to 100.
+
+ at item opacity
+Set opacity strength when using pixel format output with alpha component.
 @end table
 
 @subsection Examples
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
index c99dabad87..f09d9145b4 100644
--- a/libavfilter/avf_showspectrum.c
+++ b/libavfilter/avf_showspectrum.c
@@ -96,8 +96,8 @@ typedef struct ShowSpectrumContext {
     float overlap;
     float gain;
     int hop_size;
-    float *combine_buffer;      ///< color combining buffer (3 * h items)
-    float **color_buffer;       ///< color buffer (3 * h * ch items)
+    float *combine_buffer;      ///< color combining buffer (4 * h items)
+    float **color_buffer;       ///< color buffer (4 * h * ch items)
     int64_t pts;
     int64_t old_pts;
     int64_t in_pts;
@@ -110,6 +110,8 @@ typedef struct ShowSpectrumContext {
     uint64_t samples;
     int (*plot_channel)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
 
+    float opacity_factor;
+
     AVFrame **frames;
     unsigned int nb_frames;
     unsigned int frames_size;
@@ -174,6 +176,7 @@ static const AVOption showspectrum_options[] = {
     { "legend", "draw legend", OFFSET(legend), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
     { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS },
     { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS },
+    { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS },
     { NULL }
 };
 
@@ -360,7 +363,7 @@ static int query_formats(AVFilterContext *ctx)
     AVFilterLink *inlink = ctx->inputs[0];
     AVFilterLink *outlink = ctx->outputs[0];
     static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE };
-    static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE };
+    static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE };
     int ret;
 
     /* set input audio formats */
@@ -495,11 +498,10 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
 {
     const uint8_t *font;
     int font_height;
-    int i;
 
     font = avpriv_cga_font,   font_height =  8;
 
-    for (i = 0; txt[i]; i++) {
+    for (int i = 0; txt[i]; i++) {
         int char_y, mask;
 
         if (o) {
@@ -523,6 +525,28 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
             }
         }
     }
+
+    for (int i = 0; txt[i] && pic->data[3]; i++) {
+        int char_y, mask;
+
+        if (o) {
+            for (char_y = font_height - 1; char_y >= 0; char_y--) {
+                uint8_t *p = pic->data[3] + (y + i * 10) * pic->linesize[3] + x;
+                for (mask = 0x80; mask; mask >>= 1) {
+                    for (int k = 0; k < 8; k++)
+                        p[k] = 255;
+                    p += pic->linesize[3];
+                }
+            }
+        } else {
+            uint8_t *p = pic->data[3] + y*pic->linesize[3] + (x + i*8);
+            for (char_y = 0; char_y < font_height; char_y++) {
+                for (mask = 0x80; mask; mask >>= 1)
+                    *p++ = 255;
+                p += pic->linesize[3] - 8;
+            }
+        }
+    }
 }
 
 static void color_range(ShowSpectrumContext *s, int ch,
@@ -591,6 +615,8 @@ static void pick_color(ShowSpectrumContext *s,
                        float yf, float uf, float vf,
                        float a, float *out)
 {
+    const float af = s->opacity_factor * 255.f;
+
     if (s->color_mode > CHANNEL) {
         const int cm = s->color_mode;
         float y, u, v;
@@ -624,10 +650,12 @@ static void pick_color(ShowSpectrumContext *s,
         out[0] = y * yf;
         out[1] = u * uf;
         out[2] = v * vf;
+        out[3] = a * af;
     } else {
         out[0] = a * yf;
         out[1] = a * uf;
         out[2] = a * vf;
+        out[3] = a * af;
     }
 }
 
@@ -907,23 +935,26 @@ static int draw_legend(AVFilterContext *ctx, uint64_t samples)
         int h = multi ? s->h / s->nb_display_channels : s->h;
 
         for (y = 0; y < h; y++) {
-            float out[3] = { 0., 127.5, 127.5};
+            float out[4] = { 0., 127.5, 127.5, 0.f};
             int chn;
 
             for (chn = 0; chn < (s->mode == SEPARATE ? 1 : s->nb_display_channels); chn++) {
                 float yf, uf, vf;
                 int channel = (multi) ? s->nb_display_channels - ch - 1 : chn;
-                float lout[3];
+                float lout[4];
 
                 color_range(s, channel, &yf, &uf, &vf);
                 pick_color(s, yf, uf, vf, y / (float)h, lout);
                 out[0] += lout[0];
                 out[1] += lout[1];
                 out[2] += lout[2];
+                out[3] += lout[3];
             }
             memset(s->outpicref->data[0]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[0] + s->w + s->start_x + 20, av_clip_uint8(out[0]), 10);
             memset(s->outpicref->data[1]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[1] + s->w + s->start_x + 20, av_clip_uint8(out[1]), 10);
             memset(s->outpicref->data[2]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[2] + s->w + s->start_x + 20, av_clip_uint8(out[2]), 10);
+            if (s->outpicref->data[3])
+                memset(s->outpicref->data[3]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[3] + s->w + s->start_x + 20, av_clip_uint8(out[3]), 10);
         }
 
         for (y = 0; ch == 0 && y < h + 5; y += 25) {
@@ -985,7 +1016,7 @@ static int plot_channel_lin(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
     /* draw the channel */
     for (y = 0; y < h; y++) {
         int row = (s->mode == COMBINED) ? y : ch * h + y;
-        float *out = &s->color_buffer[ch][3 * row];
+        float *out = &s->color_buffer[ch][4 * row];
         float a = get_value(ctx, ch, y);
 
         pick_color(s, yf, uf, vf, a, out);
@@ -1016,7 +1047,7 @@ static int plot_channel_log(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
         a1 = get_value(ctx, ch, av_clip(pos+1, 0, h-1));
         {
             int row = (s->mode == COMBINED) ? yy : ch * h + yy;
-            float *out = &s->color_buffer[ch][3 * row];
+            float *out = &s->color_buffer[ch][4 * row];
 
             pick_color(s, yf, uf, vf, delta * a1 + (1.f - delta) * a0, out);
         }
@@ -1155,7 +1186,7 @@ static int config_output(AVFilterLink *outlink)
         if (!s->color_buffer)
             return AVERROR(ENOMEM);
         for (i = 0; i < s->nb_display_channels; i++) {
-            s->color_buffer[i] = av_calloc(s->orientation == VERTICAL ? s->h * 3 : s->w * 3, sizeof(**s->color_buffer));
+            s->color_buffer[i] = av_calloc(s->orientation == VERTICAL ? s->h * 4 : s->w * 4, sizeof(**s->color_buffer));
             if (!s->color_buffer[i])
                 return AVERROR(ENOMEM);
         }
@@ -1214,6 +1245,8 @@ static int config_output(AVFilterLink *outlink)
             memset(outpicref->data[0] + i * outpicref->linesize[0],   0, outlink->w);
             memset(outpicref->data[1] + i * outpicref->linesize[1], 128, outlink->w);
             memset(outpicref->data[2] + i * outpicref->linesize[2], 128, outlink->w);
+            if (outpicref->data[3])
+                memset(outpicref->data[3] + i * outpicref->linesize[3], 0, outlink->w);
         }
         outpicref->color_range = AVCOL_RANGE_JPEG;
 
@@ -1251,11 +1284,11 @@ static int config_output(AVFilterLink *outlink)
 
     if (s->orientation == VERTICAL) {
         s->combine_buffer =
-            av_realloc_f(s->combine_buffer, s->h * 3,
+            av_realloc_f(s->combine_buffer, s->h * 4,
                          sizeof(*s->combine_buffer));
     } else {
         s->combine_buffer =
-            av_realloc_f(s->combine_buffer, s->w * 3,
+            av_realloc_f(s->combine_buffer, s->w * 4,
                          sizeof(*s->combine_buffer));
     }
 
@@ -1379,9 +1412,10 @@ static void clear_combine_buffer(ShowSpectrumContext *s, int size)
     int y;
 
     for (y = 0; y < size; y++) {
-        s->combine_buffer[3 * y    ] = 0;
-        s->combine_buffer[3 * y + 1] = 127.5;
-        s->combine_buffer[3 * y + 2] = 127.5;
+        s->combine_buffer[4 * y    ] = 0;
+        s->combine_buffer[4 * y + 1] = 127.5;
+        s->combine_buffer[4 * y + 2] = 127.5;
+        s->combine_buffer[4 * y + 3] = 0;
     }
 }
 
@@ -1392,6 +1426,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
     ShowSpectrumContext *s = ctx->priv;
     AVFrame *outpicref = s->outpicref;
     int ret, plane, x, y, z = s->orientation == VERTICAL ? s->h : s->w;
+    const int alpha = outpicref->data[3] != NULL;
 
     /* fill a new spectrum column */
     /* initialize buffer for combining to black */
@@ -1399,7 +1434,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
 
     ff_filter_execute(ctx, s->plot_channel, NULL, NULL, s->nb_display_channels);
 
-    for (y = 0; y < z * 3; y++) {
+    for (y = 0; y < z * 4; y++) {
         for (x = 0; x < s->nb_display_channels; x++) {
             s->combine_buffer[y] += s->color_buffer[x][y];
         }
@@ -1409,7 +1444,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
     /* copy to output */
     if (s->orientation == VERTICAL) {
         if (s->sliding == SCROLL) {
-            for (plane = 0; plane < 3; plane++) {
+            for (plane = 0; plane < 3 + alpha; plane++) {
                 for (y = 0; y < s->h; y++) {
                     uint8_t *p = outpicref->data[plane] + s->start_x +
                                  (y + s->start_y) * outpicref->linesize[plane];
@@ -1418,7 +1453,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
             }
             s->xpos = s->w - 1;
         } else if (s->sliding == RSCROLL) {
-            for (plane = 0; plane < 3; plane++) {
+            for (plane = 0; plane < 3 + alpha; plane++) {
                 for (y = 0; y < s->h; y++) {
                     uint8_t *p = outpicref->data[plane] + s->start_x +
                                  (y + s->start_y) * outpicref->linesize[plane];
@@ -1432,13 +1467,22 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
                          (outlink->h - 1 - s->start_y) * outpicref->linesize[plane] +
                          s->xpos;
             for (y = 0; y < s->h; y++) {
-                *p = lrintf(av_clipf(s->combine_buffer[3 * y + plane], 0, 255));
+                *p = lrintf(av_clipf(s->combine_buffer[4 * y + plane], 0, 255));
                 p -= outpicref->linesize[plane];
             }
         }
+        if (alpha) {
+            uint8_t *p = outpicref->data[3] + s->start_x +
+                         (outlink->h - 1 - s->start_y) * outpicref->linesize[3] +
+                         s->xpos;
+            for (y = 0; y < s->h; y++) {
+                *p = lrintf(av_clipf(s->combine_buffer[4 * y + 3], 0, 255));
+                p -= outpicref->linesize[3];
+            }
+        }
     } else {
         if (s->sliding == SCROLL) {
-            for (plane = 0; plane < 3; plane++) {
+            for (plane = 0; plane < 3 + alpha; plane++) {
                 for (y = 1; y < s->h; y++) {
                     memmove(outpicref->data[plane] + (y-1 + s->start_y) * outpicref->linesize[plane] + s->start_x,
                             outpicref->data[plane] + (y   + s->start_y) * outpicref->linesize[plane] + s->start_x,
@@ -1447,7 +1491,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
             }
             s->xpos = s->h - 1;
         } else if (s->sliding == RSCROLL) {
-            for (plane = 0; plane < 3; plane++) {
+            for (plane = 0; plane < 3 + alpha; plane++) {
                 for (y = s->h - 1; y >= 1; y--) {
                     memmove(outpicref->data[plane] + (y   + s->start_y) * outpicref->linesize[plane] + s->start_x,
                             outpicref->data[plane] + (y-1 + s->start_y) * outpicref->linesize[plane] + s->start_x,
@@ -1460,7 +1504,15 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
             uint8_t *p = outpicref->data[plane] + s->start_x +
                          (s->xpos + s->start_y) * outpicref->linesize[plane];
             for (x = 0; x < s->w; x++) {
-                *p = lrintf(av_clipf(s->combine_buffer[3 * x + plane], 0, 255));
+                *p = lrintf(av_clipf(s->combine_buffer[4 * x + plane], 0, 255));
+                p++;
+            }
+        }
+        if (alpha) {
+            uint8_t *p = outpicref->data[3] + s->start_x +
+                         (s->xpos + s->start_y) * outpicref->linesize[3];
+            for (x = 0; x < s->w; x++) {
+                *p = lrintf(av_clipf(s->combine_buffer[4 * x + 3], 0, 255));
                 p++;
             }
         }
@@ -1576,12 +1628,16 @@ static int activate(AVFilterContext *ctx)
                 memset(s->outpicref->data[0] + i * s->outpicref->linesize[0] + s->xpos,   0, outlink->w - s->xpos);
                 memset(s->outpicref->data[1] + i * s->outpicref->linesize[1] + s->xpos, 128, outlink->w - s->xpos);
                 memset(s->outpicref->data[2] + i * s->outpicref->linesize[2] + s->xpos, 128, outlink->w - s->xpos);
+                if (s->outpicref->data[3])
+                    memset(s->outpicref->data[3] + i * s->outpicref->linesize[3] + s->xpos, 0, outlink->w - s->xpos);
             }
         } else {
             for (int i = s->xpos; i < outlink->h; i++) {
                 memset(s->outpicref->data[0] + i * s->outpicref->linesize[0],   0, outlink->w);
                 memset(s->outpicref->data[1] + i * s->outpicref->linesize[1], 128, outlink->w);
                 memset(s->outpicref->data[2] + i * s->outpicref->linesize[2], 128, outlink->w);
+                if (s->outpicref->data[3])
+                    memset(s->outpicref->data[3] + i * s->outpicref->linesize[3], 0, outlink->w);
             }
         }
         s->outpicref->pts = av_rescale_q(s->in_pts, inlink->time_base, outlink->time_base);
@@ -1687,6 +1743,7 @@ static const AVOption showspectrumpic_options[] = {
     { "stop",  "stop frequency",  OFFSET(stop),  AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
     { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS },
     { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS },
+    { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS },
     { NULL }
 };
 



More information about the ffmpeg-cvslog mailing list