|
|
@@ -867,6 +867,12 @@ typedef struct HDCDContext { |
|
|
|
const AVClass *class; |
|
|
|
hdcd_state_t state[2]; |
|
|
|
|
|
|
|
/* always extend peaks above -3dBFS even if PE isn't signaled |
|
|
|
* -af hdcd=force_pe=0 for off |
|
|
|
* -af hdcd=force_pe=1 for on |
|
|
|
* default is off */ |
|
|
|
int force_pe; |
|
|
|
|
|
|
|
AVFilterContext *fctx; /* filter context for logging errors */ |
|
|
|
int sample_count; /* used in error logging */ |
|
|
|
|
|
|
@@ -878,7 +884,10 @@ typedef struct HDCDContext { |
|
|
|
float max_gain_adjustment; /* in dB, expected in the range -6.0 to 0.0 */ |
|
|
|
} HDCDContext; |
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(HDCDContext, x) |
|
|
|
static const AVOption hdcd_options[] = { |
|
|
|
{ "force_pe", "Always extend peaks above -3dBFS even when PE is not signaled.", |
|
|
|
OFFSET(force_pe), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, 0 }, |
|
|
|
{NULL} |
|
|
|
}; |
|
|
|
|
|
|
@@ -1093,14 +1102,21 @@ static int hdcd_envelope(int32_t *samples, int count, int stride, int gain, int |
|
|
|
return gain; |
|
|
|
} |
|
|
|
|
|
|
|
/* extract fields from control code */ |
|
|
|
static void hdcd_control(HDCDContext *ctx, hdcd_state_t *state, int *peak_extend, int *target_gain) |
|
|
|
{ |
|
|
|
*peak_extend = (ctx->force_pe || state->control & 16); |
|
|
|
*target_gain = (state->control & 15) << 7; |
|
|
|
} |
|
|
|
|
|
|
|
static void hdcd_process(HDCDContext *ctx, hdcd_state_t *state, int32_t *samples, int count, int stride) |
|
|
|
{ |
|
|
|
int32_t *samples_end = samples + count * stride; |
|
|
|
int gain = state->running_gain; |
|
|
|
int peak_extend = (state->control & 16); |
|
|
|
int target_gain = (state->control & 15) << 7; |
|
|
|
int peak_extend, target_gain; |
|
|
|
int lead = 0; |
|
|
|
|
|
|
|
hdcd_control(ctx, state, &peak_extend, &target_gain); |
|
|
|
while (count > lead) { |
|
|
|
int envelope_run; |
|
|
|
int run; |
|
|
@@ -1115,8 +1131,7 @@ static void hdcd_process(HDCDContext *ctx, hdcd_state_t *state, int32_t *samples |
|
|
|
samples += envelope_run * stride; |
|
|
|
count -= envelope_run; |
|
|
|
lead = run - envelope_run; |
|
|
|
peak_extend = (state->control & 16); |
|
|
|
target_gain = (state->control & 15) << 7; |
|
|
|
hdcd_control(ctx, state, &peak_extend, &target_gain); |
|
|
|
} |
|
|
|
if (lead > 0) { |
|
|
|
av_assert0(samples + lead * stride <= samples_end); |
|
|
@@ -1285,6 +1300,9 @@ static av_cold int init(AVFilterContext *ctx) |
|
|
|
hdcd_reset(&s->state[c], 44100); |
|
|
|
} |
|
|
|
|
|
|
|
av_log(ctx, AV_LOG_VERBOSE, "Force PE: %s\n", |
|
|
|
(s->force_pe) ? "on" : "off"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|