I've attached a third attempt at this patch with all the
suggestions by Carl Eugen Hoyos and Moritz Barsnick,
including converting the UPDATE_INFO macro into a
function, and some more comments and little fixes.

Thanks.
From 2dbbfc0cea83b769b5b02eecc5ec3dabc477457b Mon Sep 17 00:00:00 2001
From: Burt P <pbu...@gmail.com>
Date: Sun, 3 Jul 2016 21:46:10 -0500
Subject: [PATCH] libavfilter/af_hdcd.c: Collect HDCD stats and report

The new HDCD filter really does nothing to show that it is working or
that HDCD control information was even detected in the stream. This
patch collects information about the decode, like which features were
used, and reports it to the user at the end.

Signed-off-by: Burt P <pbu...@gmail.com>
---
 libavfilter/af_hdcd.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c
index 16bdcb0..d00d846 100644
--- a/libavfilter/af_hdcd.c
+++ b/libavfilter/af_hdcd.c
@@ -823,11 +823,27 @@ typedef struct {
     int code_counterA;
     int code_counterB;
     int code_counterC;
+
+    /* For user information/stats, pulled up into HDCDContext
+     * by filter_frame() */
+    int hdcd_detected;     /* if ever detected */
+    int peak_extend;       /* if ever enabled */
+    int transient_filter;  /* if ever enabled */
+    /* 4-bit (3.1) fixed-point, << 7 *
+     * stored positive, but values are negative, so
+     * min and max are swapped when converted to float later */
+    int gain_min, gain_max;
 } hdcd_state_t;
 
 typedef struct HDCDContext {
     const AVClass *class;
     hdcd_state_t state[2];
+
+    /* User information/stats */
+    int hdcd_detected;
+    int uses_peak_extend;
+    int uses_transient_filter; /* detected, but not implemented */
+    float gain_min, gain_max;
 } HDCDContext;
 
 static const AVOption hdcd_options[] = {
@@ -853,6 +869,12 @@ static void hdcd_reset(hdcd_state_t *state, unsigned rate)
     state->code_counterA = 0;
     state->code_counterB = 0;
     state->code_counterC = 0;
+
+    state->hdcd_detected = 0;
+    state->peak_extend = 0;
+    state->gain_min = 0;
+    state->gain_max = 0;
+    state->transient_filter = 0;
 }
 
 static int integrate(hdcd_state_t *state, int *flag, const int32_t *samples, int count, int stride)
@@ -982,6 +1004,20 @@ static int hdcd_envelope(int32_t *samples, int count, int stride, int gain, int
     return gain;
 }
 
+/* update the user info/flags */
+static void hdcd_update_info(hdcd_state_t *state)
+{
+    int target_gain = (state->control & 15) << 7;
+    state->gain_min = FFMIN(state->gain_min, target_gain);
+    state->gain_max = FFMAX(state->gain_max, target_gain);
+    state->peak_extend |= !!(state->control & 16);
+    state->transient_filter |= !!(state->control & 32);
+    state->hdcd_detected |= target_gain
+        || state->peak_extend
+        || state->transient_filter
+        || state->sustain;
+}
+
 static void hdcd_process(hdcd_state_t *state, int32_t *samples, int count, int stride)
 {
     int32_t *samples_end = samples + count * stride;
@@ -990,6 +1026,8 @@ static void hdcd_process(hdcd_state_t *state, int32_t *samples, int count, int s
     int target_gain = (state->control & 15) << 7;
     int lead = 0;
 
+    hdcd_update_info(state);
+
     while (count > lead) {
         int envelope_run;
         int run;
@@ -1006,6 +1044,7 @@ static void hdcd_process(hdcd_state_t *state, int32_t *samples, int count, int s
         lead = run - envelope_run;
         peak_extend = (state->control & 16);
         target_gain = (state->control & 15) << 7;
+        hdcd_update_info(state);
     }
     if (lead > 0) {
         av_assert0(samples + lead * stride <= samples_end);
@@ -1015,6 +1054,9 @@ static void hdcd_process(hdcd_state_t *state, int32_t *samples, int count, int s
     state->running_gain = gain;
 }
 
+/* convert to float from (4-bit (3.1) fixed-point, << 7) */
+#define GAINTOFLOAT(g) ((float)(g>>8) + ((g>>7 & 1) ? 0.5 : 0.0))
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
     AVFilterContext *ctx = inlink->dst;
@@ -1024,6 +1066,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     const int16_t *in_data;
     int32_t *out_data;
     int n, c;
+    int gain_min = 0;
+    int gain_max = 0;
 
     out = ff_get_audio_buffer(outlink, in->nb_samples);
     if (!out) {
@@ -1042,8 +1086,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     for (c = 0; c < inlink->channels; c++) {
         hdcd_state_t *state = &s->state[c];
         hdcd_process(state, out_data + c, in->nb_samples, out->channels);
+
+        s->hdcd_detected |= state->hdcd_detected;
+        s->uses_peak_extend |= state->peak_extend;
+        s->uses_transient_filter |= state->transient_filter;
+        gain_min = FFMIN(gain_min, state->gain_min);
+        gain_max = FFMAX(gain_max, state->gain_max);
     }
 
+    /* swapped here because the fixed-point always-negative values
+     *  are stored positive */
+    s->gain_max = FFMAX(s->gain_max, -GAINTOFLOAT(gain_min)); /* max = -min */
+    s->gain_min = FFMIN(s->gain_min, -GAINTOFLOAT(gain_max)); /* min = -max */
+
     av_frame_free(&in);
     return ff_filter_frame(outlink, out);
 }
@@ -1104,6 +1159,13 @@ static av_cold void uninit(AVFilterContext *ctx)
         av_log(ctx, AV_LOG_VERBOSE, "Channel %d: counter A: %d, B: %d, C: %d\n", i, state->code_counterA,
                 state->code_counterB, state->code_counterC);
     }
+
+    av_log(ctx, AV_LOG_INFO,
+        "HDCD detected: %s, peak_extend: %s, transient_filter: %s, min_gain: %0.1f dB, max_gain: %0.1f dB\n",
+        (s->hdcd_detected) ? "yes" : "no",
+        (s->uses_peak_extend) ? "enabled" : "never enabled",
+        (s->uses_transient_filter) ? "enabled (but not supported)" : "never enabled",
+        s->gain_min, s->gain_max);
 }
 
 static av_cold int init(AVFilterContext *ctx)
@@ -1112,6 +1174,9 @@ static av_cold int init(AVFilterContext *ctx)
     HDCDContext *s = ctx->priv;
     int c;
 
+    s->gain_min = 0.0;
+    s->gain_max = 0.0;
+
     for (c = 0; c < 2; c++) {
         hdcd_reset(&s->state[c], 44100);
     }
-- 
2.7.4

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to