Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libavfilter')
-rw-r--r--libavfilter/af_hdcd.c76
1 files changed, 73 insertions, 3 deletions
diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c
index 16bdcb01ea..89012eb53e 100644
--- a/libavfilter/af_hdcd.c
+++ b/libavfilter/af_hdcd.c
@@ -31,7 +31,8 @@
*/
/*
- More information about high definition audio cds:
+ HDCD is High Definition Compatible Digital
+ More information about HDCD-encoded audio CDs:
http://www.audiomisc.co.uk/HFN/HDCD/Enigma.html
http://www.audiomisc.co.uk/HFN/HDCD/Examined.html
*/
@@ -823,11 +824,29 @@ typedef struct {
int code_counterA;
int code_counterB;
int code_counterC;
+
+ /* For user information/stats, pulled up into HDCDContext
+ * by filter_frame() */
+ int count_peak_extend;
+ int count_transient_filter;
+ /* target_gain is a 4-bit (3.1) fixed-point value, always
+ * negative, but stored positive.
+ * The 16 possible values range from -7.5 to 0.0 dB in
+ * steps of 0.5, but no value below -6.0 dB should appear. */
+ int gain_counts[16]; /* for cursiosity, mostly */
+ int max_gain;
+ int cb6, cb7; /* watch bits 6 and 7 of the control code, for curiosity */
} 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 max_gain_adjustment; /* in dB, expected in the range -6.0 to 0.0 */
} HDCDContext;
static const AVOption hdcd_options[] = {
@@ -840,6 +859,8 @@ AVFILTER_DEFINE_CLASS(hdcd);
static void hdcd_reset(hdcd_state_t *state, unsigned rate)
{
+ int i;
+
state->window = 0;
state->readahead = 32;
state->arg = 0;
@@ -853,6 +874,13 @@ static void hdcd_reset(hdcd_state_t *state, unsigned rate)
state->code_counterA = 0;
state->code_counterB = 0;
state->code_counterC = 0;
+
+ state->count_peak_extend = 0;
+ state->count_transient_filter = 0;
+ for(i = 0; i < 16; i++) state->gain_counts[i] = 0;
+ state->max_gain = 0;
+ state->cb6 = 0;
+ state->cb7 = 0;
}
static int integrate(hdcd_state_t *state, int *flag, const int32_t *samples, int count, int stride)
@@ -949,6 +977,7 @@ static int hdcd_envelope(int32_t *samples, int count, int stride, int gain, int
int len = FFMIN(count, target_gain - gain);
/* attenuate slowly */
for (i = 0; i < len; i++) {
+ ++gain;
APPLY_GAIN(*samples, gain);
samples += stride;
}
@@ -982,6 +1011,18 @@ 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)
+{
+ if (state->control & 16) state->count_peak_extend++;
+ if (state->control & 32) state->count_transient_filter++;
+ state->gain_counts[state->control & 15]++;
+ state->max_gain = FFMAX(state->max_gain, (state->control & 15));
+
+ if (state->control & 64) state->cb6++;
+ if (state->control & 128) state->cb7++;
+}
+
static void hdcd_process(hdcd_state_t *state, int32_t *samples, int count, int stride)
{
int32_t *samples_end = samples + count * stride;
@@ -990,6 +1031,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 +1049,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 +1059,10 @@ 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
+ * the always-negative value is stored positive, so make it negative */
+#define GAINTOFLOAT(g) (g) ? -(float)(g>>1) - ((g & 1) ? 0.5 : 0.0) : 0.0
+
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{
AVFilterContext *ctx = inlink->dst;
@@ -1042,6 +1090,11 @@ 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->uses_peak_extend |= !!state->count_peak_extend;
+ s->uses_transient_filter |= !!state->count_transient_filter;
+ s->max_gain_adjustment = FFMIN(s->max_gain_adjustment, GAINTOFLOAT(state->max_gain));
+ s->hdcd_detected |= state->code_counterC || state->code_counterB || state->code_counterA;
}
av_frame_free(&in);
@@ -1097,13 +1150,28 @@ static int query_formats(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
{
HDCDContext *s = ctx->priv;
- int i;
+ int i, j;
+ /* dump the state for each channel for AV_LOG_VERBOSE */
for (i = 0; i < 2; i++) {
hdcd_state_t *state = &s->state[i];
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_VERBOSE, "Channel %d: c(pe): %d, c(tf): %d, cb6: %d, cb7: %d\n", i,
+ state->count_peak_extend, state->count_transient_filter, state->cb6, state->cb7);
+ for (j = 0; j <= state->max_gain; j++) {
+ av_log(ctx, AV_LOG_VERBOSE, "Channel %d: tg %0.1f - %d\n", i, GAINTOFLOAT(j), state->gain_counts[j]);
+ }
}
+
+ /* log the HDCD decode information */
+ av_log(ctx, AV_LOG_INFO,
+ "HDCD detected: %s, peak_extend: %s, max_gain_adj: %0.1f dB, transient_filter: %s\n",
+ (s->hdcd_detected) ? "yes" : "no",
+ (s->uses_peak_extend) ? "enabled" : "never enabled",
+ s->max_gain_adjustment,
+ (s->uses_transient_filter) ? "detected" : "not detected"
+ );
}
static av_cold int init(AVFilterContext *ctx)
@@ -1112,6 +1180,8 @@ static av_cold int init(AVFilterContext *ctx)
HDCDContext *s = ctx->priv;
int c;
+ s->max_gain_adjustment = 0.0;
+
for (c = 0; c < 2; c++) {
hdcd_reset(&s->state[c], 44100);
}
@@ -1138,7 +1208,7 @@ static const AVFilterPad avfilter_af_hdcd_outputs[] = {
AVFilter ff_af_hdcd = {
.name = "hdcd",
- .description = NULL_IF_CONFIG_SMALL("Apply high definition audio cd decoding."),
+ .description = NULL_IF_CONFIG_SMALL("Apply High Definition Compatible Digital (HDCD) decoding."),
.priv_size = sizeof(HDCDContext),
.priv_class = &hdcd_class,
.init = init,