[FFmpeg-cvslog] avfilter/avf_abitscope: refactor code & add trace mode

Paul B Mahol git at videolan.org
Thu Mar 3 18:42:38 EET 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Thu Mar  3 11:31:38 2022 +0100| [de0bb77563a02d9556af8144fee88cdbedd0cdef] | committer: Paul B Mahol

avfilter/avf_abitscope: refactor code & add trace mode

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

 doc/filters.texi            |   3 +
 libavfilter/avf_abitscope.c | 138 ++++++++++++++++++++++++++++----------------
 2 files changed, 92 insertions(+), 49 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 571d9430c6..59f9dab2ea 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -25867,6 +25867,9 @@ Default value is @code{1024x256}.
 Specify list of colors separated by space or by '|' which will be used to
 draw channels. Unrecognized or missing colors will be replaced
 by white color.
+
+ at item mode, m
+Set output mode. Can be @code{bars} or @code{trace}. Default is @code{bars}.
 @end table
 
 @section adrawgraph
diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c
index f74a6eacb0..16b2d66f11 100644
--- a/libavfilter/avf_abitscope.c
+++ b/libavfilter/avf_abitscope.c
@@ -34,13 +34,17 @@ typedef struct AudioBitScopeContext {
     int w, h;
     AVRational frame_rate;
     char *colors;
+    int mode;
 
     int nb_channels;
     int nb_samples;
     int depth;
+    int current_vpos;
     uint8_t *fg;
 
     uint64_t counter[64];
+
+    AVFrame *outpicref;
 } AudioBitScopeContext;
 
 #define OFFSET(x) offsetof(AudioBitScopeContext, x)
@@ -52,6 +56,10 @@ static const AVOption abitscope_options[] = {
     { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS },
     { "s",    "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS },
     { "colors", "set channels colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0, FLAGS },
+    { "mode", "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "mode" },
+    { "m",    "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "mode" },
+    { "bars",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "mode" },
+    { "trace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "mode" },
     { NULL }
 };
 
@@ -146,75 +154,99 @@ static void count_bits(AudioBitScopeContext *s, uint32_t sample, int max)
     }
 }
 
+
+#define BARS(type, depth)                                                   \
+    for (int ch = 0; ch < inlink->channels; ch++) {                         \
+        const type *in = (const type *)insamples->extended_data[ch];        \
+        const int w = outpicref->width / inlink->channels;                  \
+        const int h = outpicref->height / depth;                            \
+        const uint32_t color = AV_RN32(&s->fg[4 * ch]);                     \
+                                                                            \
+        memset(s->counter, 0, sizeof(s->counter));                          \
+        for (int i = 0; i < insamples->nb_samples; i++)                     \
+            count_bits(s, in[i], depth);                                    \
+                                                                            \
+        for (int b = 0; b < depth; b++) {                                   \
+            for (int j = 1; j < h - 1; j++) {                               \
+                uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; \
+                const int ww = (s->counter[depth - b - 1] / (float)insamples->nb_samples) * (w - 1); \
+                                                                            \
+                for (int i = 0; i < ww; i++) {                              \
+                    AV_WN32(&dst[i * 4], color);                            \
+                }                                                           \
+            }                                                               \
+        }                                                                   \
+    }
+
+#define TRACE(type, depth)                                                  \
+    for (int ch = 0; ch < inlink->channels; ch++) {                         \
+        const int w = outpicref->width / inlink->channels;                  \
+        const type *in = (const type *)insamples->extended_data[ch];        \
+        const int wb = w / depth;                                           \
+        int wv;                                                             \
+                                                                            \
+        memset(s->counter, 0, sizeof(s->counter));                          \
+        for (int i = 0; i < insamples->nb_samples; i++)                     \
+            count_bits(s, in[i], depth);                                    \
+                                                                            \
+        for (int b = 0; b < depth; b++) {                                   \
+            uint8_t colors[4];                                              \
+            uint32_t color;                                                 \
+            uint8_t *dst = outpicref->data[0] + w * ch * 4 + wb * b * 4 +   \
+                           s->current_vpos * outpicref->linesize[0];        \
+            wv = (s->counter[depth - b - 1] * 255) / insamples->nb_samples; \
+            colors[0] = (wv * s->fg[ch * 4 + 0] + 127) / 255;               \
+            colors[1] = (wv * s->fg[ch * 4 + 1] + 127) / 255;               \
+            colors[2] = (wv * s->fg[ch * 4 + 2] + 127) / 255;               \
+            colors[3] = (wv * s->fg[ch * 4 + 3] + 127) / 255;               \
+            color = AV_RN32(colors);                                        \
+                                                                            \
+            for (int x = 0; x < wb; x++)                                    \
+                AV_WN32(&dst[x * 4], color);                                \
+        }                                                                   \
+    }
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
 {
     AVFilterContext *ctx = inlink->dst;
     AVFilterLink *outlink = ctx->outputs[0];
     AudioBitScopeContext *s = ctx->priv;
     AVFrame *outpicref;
-    int ch, i, j, b;
 
-    outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!outpicref) {
-        av_frame_free(&insamples);
-        return AVERROR(ENOMEM);
+    if (s->mode == 0 || !s->outpicref) {
+        outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+        if (!outpicref) {
+            av_frame_free(&insamples);
+            return AVERROR(ENOMEM);
+        }
+
+        for (int i = 0; i < outlink->h; i++)
+            memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4);
+        if (!s->outpicref && s->mode == 1)
+            s->outpicref = outpicref;
     }
 
-    for (i = 0; i < outlink->h; i++)
-        memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4);
+    if (s->mode == 1) {
+        outpicref = av_frame_clone(s->outpicref);
+        if (!outpicref)
+            return AVERROR(ENOMEM);
+    }
 
     outpicref->pts = insamples->pts;
     outpicref->sample_aspect_ratio = (AVRational){1,1};
 
     switch (insamples->format) {
     case AV_SAMPLE_FMT_S16P:
-        for (ch = 0; ch < inlink->channels; ch++) {
-            uint16_t *in = (uint16_t *)insamples->extended_data[ch];
-            int w = outpicref->width / inlink->channels;
-            int h = outpicref->height / 16;
-            uint32_t color = AV_RN32(&s->fg[4 * ch]);
-
-            memset(s->counter, 0, sizeof(s->counter));
-            for (i = 0; i < insamples->nb_samples; i++)
-                count_bits(s, in[i], 16);
-
-            for (b = 0; b < 16; b++) {
-                for (j = 1; j < h - 1; j++) {
-                    uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4;
-                    int ww = (s->counter[16 - b - 1] / (float)insamples->nb_samples) * (w - 1);
-
-                    for (i = 0; i < ww; i++) {
-                        AV_WN32(&dst[i * 4], color);
-                    }
-                }
-            }
-        }
+        if (s->mode == 0) { BARS(uint16_t, 16) } else { TRACE(uint16_t, 16) }
         break;
     case AV_SAMPLE_FMT_S32P:
-        for (ch = 0; ch < inlink->channels; ch++) {
-            uint32_t *in = (uint32_t *)insamples->extended_data[ch];
-            int w = outpicref->width / inlink->channels;
-            int h = outpicref->height / 32;
-            uint32_t color = AV_RN32(&s->fg[4 * ch]);
-
-            memset(s->counter, 0, sizeof(s->counter));
-            for (i = 0; i < insamples->nb_samples; i++)
-                count_bits(s, in[i], 32);
-
-            for (b = 0; b < 32; b++) {
-                for (j = 1; j < h - 1; j++) {
-                    uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4;
-                    int ww = (s->counter[32 - b - 1] / (float)insamples->nb_samples) * (w - 1);
-
-                    for (i = 0; i < ww; i++) {
-                        AV_WN32(&dst[i * 4], color);
-                    }
-                }
-            }
-        }
+        if (s->mode == 0) { BARS(uint32_t, 32) } else { TRACE(uint32_t, 32) }
         break;
     }
 
+    s->current_vpos++;
+    if (s->current_vpos >= outlink->h)
+        s->current_vpos = 0;
     av_frame_free(&insamples);
 
     return ff_filter_frame(outlink, outpicref);
@@ -242,6 +274,13 @@ static int activate(AVFilterContext *ctx)
     return FFERROR_NOT_READY;
 }
 
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    AudioBitScopeContext *s = ctx->priv;
+
+    av_frame_free(&s->outpicref);
+}
+
 static const AVFilterPad inputs[] = {
     {
         .name         = "default",
@@ -265,6 +304,7 @@ const AVFilter ff_avf_abitscope = {
     FILTER_INPUTS(inputs),
     FILTER_OUTPUTS(outputs),
     FILTER_QUERY_FUNC(query_formats),
+    .uninit        = uninit,
     .activate      = activate,
     .priv_class    = &abitscope_class,
 };



More information about the ffmpeg-cvslog mailing list