[FFmpeg-cvslog] avfilter/af_astats: extend and improve bit depth output

Paul B Mahol git at videolan.org
Mon Sep 25 20:58:11 EEST 2023


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Fri Aug 25 10:44:09 2023 +0200| [fb05bc8eee95e1b08b6d30fbb611161c4feaf76b] | committer: Paul B Mahol

avfilter/af_astats: extend and improve bit depth output

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

 libavfilter/af_astats.c | 95 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 64 insertions(+), 31 deletions(-)

diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c
index c47bd768cc..38d67175fa 100644
--- a/libavfilter/af_astats.c
+++ b/libavfilter/af_astats.c
@@ -76,7 +76,7 @@ typedef struct ChannelStats {
     double diff1_sum;
     double diff1_sum_x2;
     double abs_peak;
-    uint64_t mask, imask;
+    uint64_t mask[4];
     uint64_t min_count, max_count;
     uint64_t abs_peak_count;
     uint64_t noise_floor_count;
@@ -88,6 +88,7 @@ typedef struct ChannelStats {
     double *win_samples;
     double *sorted_samples;
     uint64_t ehistogram[HISTOGRAM_SIZE];
+    int64_t lasti;
     int sorted_front;
     int sorted_back;
     int win_pos;
@@ -178,8 +179,10 @@ static void reset_stats(AudioStatsContext *s)
         p->max_runs = 0;
         p->diff1_sum = 0;
         p->diff1_sum_x2 = 0;
-        p->mask = 0;
-        p->imask = 0xFFFFFFFFFFFFFFFF;
+        p->mask[0] = 0;
+        p->mask[1] = 0;
+        p->mask[2] =~0;
+        p->mask[3] = 0;
         p->min_count = 0;
         p->max_count = 0;
         p->abs_peak_count = 0;
@@ -239,20 +242,28 @@ static int config_output(AVFilterLink *outlink)
     return 0;
 }
 
-static void bit_depth(AudioStatsContext *s, uint64_t mask, uint64_t imask, AVRational *depth)
+static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
 {
     unsigned result = s->maxbitdepth;
+    uint64_t amask = mask[1] & (~mask[2]);
 
-    mask = mask & (~imask);
+    depth[0] = 0;
+    for (int i = 0; i < result; i++)
+        depth[0] += !!(mask[0] & (1ULL << i));
 
-    for (; result && !(mask & 1); --result, mask >>= 1);
+    depth[1] = 0;
+    for (int i = 0; i < result; i++)
+        depth[1] += !!(mask[1] & (1ULL << i));
 
-    depth->den = result;
-    depth->num = 0;
+    depth[2] = result;
+    for (int i = 0; i < result && !(amask & 1); i++) {
+        depth[2]--;
+        amask >>= 1;
+    }
 
-    for (; result; --result, mask >>= 1)
-        if (mask & 1)
-            depth->num++;
+    depth[3] = 0;
+    for (int i = 0; i < result; i++)
+        depth[3] += !!(mask[3] & (1ULL << i));
 }
 
 static double calc_entropy(AudioStatsContext *s, ChannelStats *p)
@@ -389,9 +400,13 @@ static inline void update_stat(AudioStatsContext *s, ChannelStats *p, double d,
         p->diff1_sum += fabs(d - p->last);
         p->diff1_sum_x2 += (d - p->last) * (d - p->last);
     }
+    p->mask[0] |= (i < 0) ? -i : i;
+    p->mask[1] |= i;
+    p->mask[2] &= i;
+    if (!isnan(p->last))
+        p->mask[3] |= i ^ p->lasti;
+    p->lasti = i;
     p->last = d;
-    p->mask |= i;
-    p->imask &= i;
 
     drop = p->win_samples[p->win_pos];
     p->win_samples[p->win_pos] = nd;
@@ -462,7 +477,7 @@ static void set_meta(AVDictionary **metadata, int chan, const char *key,
 
 static void set_metadata(AudioStatsContext *s, AVDictionary **metadata)
 {
-    uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0;
+    uint64_t mask[4], min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0;
     uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0;
     uint64_t abs_peak_count = 0;
     double min_runs = 0, max_runs = 0,
@@ -476,9 +491,14 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata)
            entropy = 0,
            min_sigma_x2 = DBL_MAX,
            max_sigma_x2 =-DBL_MAX;
-    AVRational depth;
+    uint8_t depth[4];
     int c;
 
+    mask[0] = 0;
+    mask[1] = 0;
+    mask[2] =~0;
+    mask[3] = 0;
+
     for (c = 0; c < s->nb_channels; c++) {
         ChannelStats *p = &s->chstats[c];
 
@@ -505,8 +525,10 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata)
         abs_peak_count += p->abs_peak_count;
         min_runs += p->min_runs;
         max_runs += p->max_runs;
-        mask |= p->mask;
-        imask &= p->imask;
+        mask[0] |= p->mask[0];
+        mask[1] |= p->mask[1];
+        mask[2] &= p->mask[2];
+        mask[3] |= p->mask[3];
         nb_samples += p->nb_samples;
         nb_nans += p->nb_nans;
         nb_infs += p->nb_infs;
@@ -551,9 +573,11 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata)
         if (s->measure_perchannel & MEASURE_ENTROPY)
             set_meta(metadata, c + 1, "Entropy", "%f", p->entropy);
         if (s->measure_perchannel & MEASURE_BIT_DEPTH) {
-            bit_depth(s, p->mask, p->imask, &depth);
-            set_meta(metadata, c + 1, "Bit_depth", "%f", depth.num);
-            set_meta(metadata, c + 1, "Bit_depth2", "%f", depth.den);
+            bit_depth(s, p->mask, depth);
+            set_meta(metadata, c + 1, "Bit_depth", "%f", depth[0]);
+            set_meta(metadata, c + 1, "Bit_depth2", "%f", depth[1]);
+            set_meta(metadata, c + 1, "Bit_depth3", "%f", depth[2]);
+            set_meta(metadata, c + 1, "Bit_depth4", "%f", depth[3]);
         }
         if (s->measure_perchannel & MEASURE_DYNAMIC_RANGE)
             set_meta(metadata, c + 1, "Dynamic_range", "%f", LINEAR_TO_DB(2 * FFMAX(FFABS(p->min), FFABS(p->max))/ p->min_non_zero));
@@ -604,9 +628,11 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata)
     if (s->measure_overall & MEASURE_ENTROPY)
         set_meta(metadata, 0, "Overall.Entropy", "%f", entropy / (double)s->nb_channels);
     if (s->measure_overall & MEASURE_BIT_DEPTH) {
-        bit_depth(s, mask, imask, &depth);
-        set_meta(metadata, 0, "Overall.Bit_depth", "%f", depth.num);
-        set_meta(metadata, 0, "Overall.Bit_depth2", "%f", depth.den);
+        bit_depth(s, mask, depth);
+        set_meta(metadata, 0, "Overall.Bit_depth", "%f", depth[0]);
+        set_meta(metadata, 0, "Overall.Bit_depth2", "%f", depth[1]);
+        set_meta(metadata, 0, "Overall.Bit_depth3", "%f", depth[2]);
+        set_meta(metadata, 0, "Overall.Bit_depth4", "%f", depth[3]);
     }
     if (s->measure_overall & MEASURE_NUMBER_OF_SAMPLES)
         set_meta(metadata, 0, "Overall.Number_of_samples", "%f", nb_samples / s->nb_channels);
@@ -724,7 +750,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
 static void print_stats(AVFilterContext *ctx)
 {
     AudioStatsContext *s = ctx->priv;
-    uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0;
+    uint64_t mask[4], min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0;
     uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0, abs_peak_count = 0;
     double min_runs = 0, max_runs = 0,
            min = DBL_MAX, max =-DBL_MAX, min_diff = DBL_MAX, max_diff = 0,
@@ -737,9 +763,14 @@ static void print_stats(AVFilterContext *ctx)
            entropy = 0,
            min_sigma_x2 = DBL_MAX,
            max_sigma_x2 =-DBL_MAX;
-    AVRational depth;
+    uint8_t depth[4];
     int c;
 
+    mask[0] = 0;
+    mask[1] = 0;
+    mask[2] =~0;
+    mask[3] = 0;
+
     for (c = 0; c < s->nb_channels; c++) {
         ChannelStats *p = &s->chstats[c];
 
@@ -769,8 +800,10 @@ static void print_stats(AVFilterContext *ctx)
         noise_floor_count += p->noise_floor_count;
         min_runs += p->min_runs;
         max_runs += p->max_runs;
-        mask |= p->mask;
-        imask &= p->imask;
+        mask[0] |= p->mask[0];
+        mask[1] |= p->mask[1];
+        mask[2] &= p->mask[2];
+        mask[3] |= p->mask[3];
         nb_samples += p->nb_samples;
         nb_nans += p->nb_nans;
         nb_infs += p->nb_infs;
@@ -818,8 +851,8 @@ static void print_stats(AVFilterContext *ctx)
         if (s->measure_perchannel & MEASURE_ENTROPY)
             av_log(ctx, AV_LOG_INFO, "Entropy: %f\n", p->entropy);
         if (s->measure_perchannel & MEASURE_BIT_DEPTH) {
-            bit_depth(s, p->mask, p->imask, &depth);
-            av_log(ctx, AV_LOG_INFO, "Bit depth: %u/%u\n", depth.num, depth.den);
+            bit_depth(s, p->mask, depth);
+            av_log(ctx, AV_LOG_INFO, "Bit depth: %u/%u/%u/%u\n", depth[0], depth[1], depth[2], depth[3]);
         }
         if (s->measure_perchannel & MEASURE_DYNAMIC_RANGE)
             av_log(ctx, AV_LOG_INFO, "Dynamic range: %f\n", LINEAR_TO_DB(2 * FFMAX(FFABS(p->min), FFABS(p->max))/ p->min_non_zero));
@@ -876,8 +909,8 @@ static void print_stats(AVFilterContext *ctx)
     if (s->measure_overall & MEASURE_ENTROPY)
         av_log(ctx, AV_LOG_INFO, "Entropy: %f\n", entropy / (double)s->nb_channels);
     if (s->measure_overall & MEASURE_BIT_DEPTH) {
-        bit_depth(s, mask, imask, &depth);
-        av_log(ctx, AV_LOG_INFO, "Bit depth: %u/%u\n", depth.num, depth.den);
+        bit_depth(s, mask, depth);
+        av_log(ctx, AV_LOG_INFO, "Bit depth: %u/%u/%u/%u\n", depth[0], depth[1], depth[2], depth[3]);
     }
     if (s->measure_overall & MEASURE_NUMBER_OF_SAMPLES)
         av_log(ctx, AV_LOG_INFO, "Number of samples: %"PRId64"\n", nb_samples / s->nb_channels);



More information about the ffmpeg-cvslog mailing list