[FFmpeg-cvslog] avfilter/avf_ahistogram: add new histogram mode option

Paul B Mahol git at videolan.org
Sat Mar 5 23:13:03 EET 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Sat Mar  5 21:56:31 2022 +0100| [fb5e871937348c6bf59cc6c640cfb3305a092f4f] | committer: Paul B Mahol

avfilter/avf_ahistogram: add new histogram mode option

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

 doc/filters.texi             | 12 ++++++++
 libavfilter/avf_ahistogram.c | 67 +++++++++++++++++++++++++++++++++++++-------
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 15d9d0fd8d..da8d12604a 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -25969,6 +25969,18 @@ replace old rows with new ones.
 scroll from top to bottom.
 @end table
 Default is @code{replace}.
+
+ at item hmode
+Set histogram mode.
+
+It accepts the following values:
+ at table @samp
+ at item abs
+Use absolute values of samples.
+ at item sign
+Use untouched values of samples.
+ at end table
+Default is @code{abs}.
 @end table
 
 @section aphasemeter
diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c
index 7ae5dd180a..03093a162f 100644
--- a/libavfilter/avf_ahistogram.c
+++ b/libavfilter/avf_ahistogram.c
@@ -32,7 +32,7 @@ enum DisplayScale   { LINEAR, SQRT, CBRT, LOG, RLOG, NB_SCALES };
 enum AmplitudeScale { ALINEAR, ALOG, NB_ASCALES };
 enum SlideMode      { REPLACE, SCROLL, NB_SLIDES };
 enum DisplayMode    { SINGLE, SEPARATE, NB_DMODES };
-enum HistogramMode  { ACCUMULATE, CURRENT, NB_HMODES };
+enum HistogramMode  { ABS, SIGN, NB_HMODES };
 
 typedef struct AudioHistogramContext {
     const AVClass *class;
@@ -49,6 +49,7 @@ typedef struct AudioHistogramContext {
     int ypos;
     int slide;
     int dmode;
+    int hmode;
     int dchannels;
     int count;
     int frame_count;
@@ -56,6 +57,8 @@ typedef struct AudioHistogramContext {
     AVFrame *in[101];
     int first;
     int nb_samples;
+
+    int (*get_bin)(float in, int w);
 } AudioHistogramContext;
 
 #define OFFSET(x) offsetof(AudioHistogramContext, x)
@@ -83,6 +86,9 @@ static const AVOption ahistogram_options[] = {
     { "slide", "set sonogram sliding", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=REPLACE}, 0, NB_SLIDES-1, FLAGS, "slide" },
         { "replace", "replace old rows with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE},    0, 0, FLAGS, "slide" },
         { "scroll",  "scroll from top to bottom", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, FLAGS, "slide" },
+    { "hmode", "set histograms mode", OFFSET(hmode), AV_OPT_TYPE_INT, {.i64=ABS}, 0, NB_HMODES-1, FLAGS, "hmode" },
+        { "abs",  "use absolute samples",  0, AV_OPT_TYPE_CONST, {.i64=ABS}, 0, 0, FLAGS, "hmode" },
+        { "sign", "use unchanged samples", 0, AV_OPT_TYPE_CONST, {.i64=SIGN},0, 0, FLAGS, "hmode" },
     { NULL }
 };
 
@@ -133,6 +139,26 @@ static int config_input(AVFilterLink *inlink)
     return 0;
 }
 
+static int get_lin_bin_abs(float in, int w)
+{
+    return lrintf(av_clipf(fabsf(in), 0.f, 1.f) * (w - 1));
+}
+
+static int get_lin_bin_sign(float in, int w)
+{
+    return lrintf((1.f + av_clipf(in, -1.f, 1.f)) * 0.5f * (w - 1));
+}
+
+static int get_log_bin_abs(float in, int w)
+{
+    return lrintf(av_clipf(1.f + log10f(fabsf(in)) / 6.f, 0.f, 1.f) * (w - 1));
+}
+
+static int get_log_bin_sign(float in, int w)
+{
+    return (w / 2) + FFSIGN(in) * lrintf(av_clipf(1.f + log10f(fabsf(in)) / 6.f, 0.f, 1.f) * (w / 2));
+}
+
 static int config_output(AVFilterLink *outlink)
 {
     AudioHistogramContext *s = outlink->src->priv;
@@ -145,6 +171,27 @@ static int config_output(AVFilterLink *outlink)
     s->histogram_h = s->h * s->phisto;
     s->ypos = s->h * s->phisto;
 
+    switch (s->ascale) {
+    case ALINEAR:
+        switch (s->hmode) {
+        case ABS:  s->get_bin = get_lin_bin_abs;  break;
+        case SIGN: s->get_bin = get_lin_bin_sign; break;
+        default:
+            return AVERROR_BUG;
+        }
+        break;
+    case ALOG:
+        switch (s->hmode) {
+        case ABS:  s->get_bin = get_log_bin_abs;  break;
+        case SIGN: s->get_bin = get_log_bin_sign; break;
+        default:
+            return AVERROR_BUG;
+        }
+        break;
+    default:
+        return AVERROR_BUG;
+    }
+
     if (s->dmode == SEPARATE) {
         s->combine_buffer = av_malloc_array(outlink->w * 3, sizeof(*s->combine_buffer));
         if (!s->combine_buffer)
@@ -207,7 +254,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w];
 
             for (n = 0; n < in->nb_samples; n++) {
-                bin = lrint(av_clipf(fabsf(src[n]), 0, 1) * (w - 1));
+                bin = s->get_bin(src[n], w);
 
                 achistogram[bin]++;
             }
@@ -217,7 +264,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                 const float *src2 = (const float *)s->in[s->first]->extended_data[c];
 
                 for (n = 0; n < in->nb_samples; n++) {
-                    bin = lrint(av_clipf(fabsf(src2[n]), 0, 1) * (w - 1));
+                    bin = s->get_bin(src2[n], w);
 
                     shistogram[bin]++;
                 }
@@ -230,7 +277,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w];
 
             for (n = 0; n < in->nb_samples; n++) {
-                bin = lrint(av_clipf(1 + log10(fabsf(src[n])) / 6, 0, 1) * (w - 1));
+                bin = s->get_bin(src[n], w);
 
                 achistogram[bin]++;
             }
@@ -240,7 +287,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                 const float *src2 = (const float *)s->in[s->first]->extended_data[c];
 
                 for (n = 0; n < in->nb_samples; n++) {
-                    bin = lrint(av_clipf(1 + log10(fabsf(src2[n])) / 6, 0, 1) * (w - 1));
+                    bin = s->get_bin(src2[n], w);
 
                     shistogram[bin]++;
                 }
@@ -265,7 +312,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         float yf, uf, vf;
 
         if (s->dmode == SEPARATE) {
-            yf = 256.0f / s->dchannels;
+            yf = 255.0f / s->dchannels;
             uf = yf * M_PI;
             vf = yf * M_PI;
             uf *= 0.5 * sin((2 * M_PI * c) / s->dchannels);
@@ -312,7 +359,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                 if (s->h - H > 0) {
                     h = aa * 255;
 
-                    s->out->data[0][s->ypos * s->out->linesize[0] + n] = h;
+                    s->out->data[0][s->ypos * s->out->linesize[0] + n] = av_clip(h, 0, 255);
                     s->out->data[1][s->ypos * s->out->linesize[1] + n] = 127;
                     s->out->data[2][s->ypos * s->out->linesize[2] + n] = 127;
                     s->out->data[3][s->ypos * s->out->linesize[3] + n] = 255;
@@ -326,9 +373,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                     if (s->out->data[0][y * s->out->linesize[0] + n] != old)
                         break;
                     old = s->out->data[0][y * s->out->linesize[0] + n];
-                    s->out->data[0][y * s->out->linesize[0] + n] = yf;
-                    s->out->data[1][y * s->out->linesize[1] + n] = 128+uf;
-                    s->out->data[2][y * s->out->linesize[2] + n] = 128+vf;
+                    s->out->data[0][y * s->out->linesize[0] + n] = av_clip(yf, 0, 255);
+                    s->out->data[1][y * s->out->linesize[1] + n] = av_clip(128.f+uf, 0, 255);
+                    s->out->data[2][y * s->out->linesize[2] + n] = av_clip(128.f+vf, 0, 255);
                     s->out->data[3][y * s->out->linesize[3] + n] = 255;
                 }
 



More information about the ffmpeg-cvslog mailing list