|
|
|
@ -872,13 +872,13 @@ typedef struct { |
|
|
|
|
int count_sustain_expired; |
|
|
|
|
|
|
|
|
|
int _ana_snb; /**< used in the analyze mode tone generator */ |
|
|
|
|
} hdcd_state_t; |
|
|
|
|
} hdcd_state; |
|
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
|
HDCD_PE_NEVER = 0, /**< All valid packets have PE set to off */ |
|
|
|
|
HDCD_PE_INTERMITTENT = 1, /**< Some valid packets have PE set to on */ |
|
|
|
|
HDCD_PE_PERMANENT = 2, /**< All valid packets have PE set to on */ |
|
|
|
|
} hdcd_pe_t; |
|
|
|
|
} hdcd_pe; |
|
|
|
|
|
|
|
|
|
static const char * const pe_str[] = { |
|
|
|
|
"never enabled", |
|
|
|
@ -890,31 +890,31 @@ typedef enum { |
|
|
|
|
HDCD_NONE = 0, /**< HDCD packets do not (yet) appear */ |
|
|
|
|
HDCD_NO_EFFECT = 1, /**< HDCD packets appear, but all control codes are NOP */ |
|
|
|
|
HDCD_EFFECTUAL = 2, /**< HDCD packets appear, and change the output in some way */ |
|
|
|
|
} hdcd_detection_t; |
|
|
|
|
} hdcd_dv; |
|
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
|
HDCD_PVER_NONE = 0, /**< No packets (yet) discovered */ |
|
|
|
|
HDCD_PVER_A = 1, /**< Packets of type A (8-bit control) discovered */ |
|
|
|
|
HDCD_PVER_B = 2, /**< Packets of type B (8-bit control, 8-bit XOR) discovered */ |
|
|
|
|
HDCD_PVER_MIX = 3, /**< Packets of type A and B discovered, most likely an encoding error */ |
|
|
|
|
} hdcd_pf_t; |
|
|
|
|
} hdcd_pf; |
|
|
|
|
|
|
|
|
|
static const char * const pf_str[] = { |
|
|
|
|
"?", "A", "B", "A+B" |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
hdcd_detection_t hdcd_detected; |
|
|
|
|
hdcd_pf_t packet_type; |
|
|
|
|
hdcd_dv hdcd_detected; |
|
|
|
|
hdcd_pf packet_type; |
|
|
|
|
int total_packets; /**< valid packets */ |
|
|
|
|
int errors; /**< detectable errors */ |
|
|
|
|
hdcd_pe_t peak_extend; |
|
|
|
|
hdcd_pe peak_extend; |
|
|
|
|
int uses_transient_filter; |
|
|
|
|
float max_gain_adjustment; /**< in dB, expected in the range -7.5 to 0.0 */ |
|
|
|
|
int cdt_expirations; /**< -1 for never set, 0 for set but never expired */ |
|
|
|
|
|
|
|
|
|
int _active_count; /**< used internally */ |
|
|
|
|
} hdcd_detection_data_t; |
|
|
|
|
} hdcd_detection_data; |
|
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
|
HDCD_ANA_OFF = 0, |
|
|
|
@ -923,7 +923,7 @@ typedef enum { |
|
|
|
|
HDCD_ANA_CDT = 3, |
|
|
|
|
HDCD_ANA_TGM = 4, |
|
|
|
|
HDCD_ANA_TOP = 5, /**< used in max value of AVOption */ |
|
|
|
|
} hdcd_ana_mode_t; |
|
|
|
|
} hdcd_ana_mode; |
|
|
|
|
|
|
|
|
|
/** analyze mode descriptions: macro for AVOption definitions, array of const char for mapping mode to string */ |
|
|
|
|
#define HDCD_ANA_OFF_DESC "disabled" |
|
|
|
@ -941,7 +941,7 @@ static const char * const ana_mode_str[] = { |
|
|
|
|
|
|
|
|
|
typedef struct HDCDContext { |
|
|
|
|
const AVClass *class; |
|
|
|
|
hdcd_state_t state[HDCD_MAX_CHANNELS]; |
|
|
|
|
hdcd_state state[HDCD_MAX_CHANNELS]; |
|
|
|
|
|
|
|
|
|
/* AVOption members */ |
|
|
|
|
/** use hdcd_*_stereo() functions to process both channels together.
|
|
|
|
@ -975,7 +975,7 @@ typedef struct HDCDContext { |
|
|
|
|
int val_target_gain; /**< last matching target_gain in both channels */ |
|
|
|
|
|
|
|
|
|
/* User information/stats */ |
|
|
|
|
hdcd_detection_data_t detect; |
|
|
|
|
hdcd_detection_data detect; |
|
|
|
|
} HDCDContext; |
|
|
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(HDCDContext, x) |
|
|
|
@ -1001,7 +1001,7 @@ static const AVOption hdcd_options[] = { |
|
|
|
|
|
|
|
|
|
AVFILTER_DEFINE_CLASS(hdcd); |
|
|
|
|
|
|
|
|
|
static void hdcd_reset(hdcd_state_t *state, unsigned rate, unsigned cdt_ms) |
|
|
|
|
static void hdcd_reset(hdcd_state *state, unsigned rate, unsigned cdt_ms) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
@ -1031,7 +1031,7 @@ static void hdcd_reset(hdcd_state_t *state, unsigned rate, unsigned cdt_ms) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** update the user info/counters */ |
|
|
|
|
static void hdcd_update_info(hdcd_state_t *state) |
|
|
|
|
static void hdcd_update_info(hdcd_state *state) |
|
|
|
|
{ |
|
|
|
|
if (state->control & 16) state->count_peak_extend++; |
|
|
|
|
if (state->control & 32) state->count_transient_filter++; |
|
|
|
@ -1047,9 +1047,9 @@ typedef enum { |
|
|
|
|
HDCD_CODE_B_CHECKFAIL, |
|
|
|
|
HDCD_CODE_EXPECT_A, |
|
|
|
|
HDCD_CODE_EXPECT_B, |
|
|
|
|
} hdcd_code_result_t; |
|
|
|
|
} hdcd_code_result; |
|
|
|
|
|
|
|
|
|
static hdcd_code_result_t hdcd_code(const uint32_t bits, unsigned char *code) |
|
|
|
|
static hdcd_code_result hdcd_code(const uint32_t bits, unsigned char *code) |
|
|
|
|
{ |
|
|
|
|
if ((bits & 0x0fa00500) == 0x0fa00500) { |
|
|
|
|
/* A: 8-bit code 0x7e0fa005[..] */ |
|
|
|
@ -1078,7 +1078,7 @@ static hdcd_code_result_t hdcd_code(const uint32_t bits, unsigned char *code) |
|
|
|
|
return HDCD_CODE_NONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int hdcd_integrate(HDCDContext *ctx, hdcd_state_t *state, int *flag, const int32_t *samples, int count, int stride) |
|
|
|
|
static int hdcd_integrate(HDCDContext *ctx, hdcd_state *state, int *flag, const int32_t *samples, int count, int stride) |
|
|
|
|
{ |
|
|
|
|
uint32_t bits = 0; |
|
|
|
|
int result = FFMIN(state->readahead, count); |
|
|
|
@ -1213,7 +1213,7 @@ static int hdcd_integrate_stereo(HDCDContext *ctx, int *flag, const int32_t *sam |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void hdcd_sustain_reset(hdcd_state_t *state) |
|
|
|
|
static void hdcd_sustain_reset(hdcd_state *state) |
|
|
|
|
{ |
|
|
|
|
state->sustain = state->sustain_reset; |
|
|
|
|
/* if this is the first reset then change
|
|
|
|
@ -1222,7 +1222,7 @@ static void hdcd_sustain_reset(hdcd_state_t *state) |
|
|
|
|
state->count_sustain_expired = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int hdcd_scan(HDCDContext *ctx, hdcd_state_t *state, const int32_t *samples, int max, int stride) |
|
|
|
|
static int hdcd_scan(HDCDContext *ctx, hdcd_state *state, const int32_t *samples, int max, int stride) |
|
|
|
|
{ |
|
|
|
|
int result; |
|
|
|
|
int cdt_active = 0; |
|
|
|
@ -1297,7 +1297,7 @@ static int hdcd_scan_stereo(HDCDContext *ctx, const int32_t *samples, int max) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** replace audio with solid tone, but save LSBs */ |
|
|
|
|
static void hdcd_analyze_prepare(hdcd_state_t *state, int32_t *samples, int count, int stride) { |
|
|
|
|
static void hdcd_analyze_prepare(hdcd_state *state, int32_t *samples, int count, int stride) { |
|
|
|
|
int n; |
|
|
|
|
for (n = 0; n < count * stride; n += stride) { |
|
|
|
|
/* in analyze mode, the audio is replaced by a solid tone, and
|
|
|
|
@ -1446,7 +1446,7 @@ static int hdcd_envelope(int32_t *samples, int count, int stride, int gain, int |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** extract fields from control code */ |
|
|
|
|
static void hdcd_control(HDCDContext *ctx, hdcd_state_t *state, int *peak_extend, int *target_gain) |
|
|
|
|
static void hdcd_control(HDCDContext *ctx, hdcd_state *state, int *peak_extend, int *target_gain) |
|
|
|
|
{ |
|
|
|
|
*peak_extend = (ctx->force_pe || state->control & 16); |
|
|
|
|
*target_gain = (state->control & 15) << 7; |
|
|
|
@ -1455,9 +1455,9 @@ static void hdcd_control(HDCDContext *ctx, hdcd_state_t *state, int *peak_extend |
|
|
|
|
typedef enum { |
|
|
|
|
HDCD_OK=0, |
|
|
|
|
HDCD_TG_MISMATCH |
|
|
|
|
} hdcd_control_result_t; |
|
|
|
|
} hdcd_control_result; |
|
|
|
|
|
|
|
|
|
static hdcd_control_result_t hdcd_control_stereo(HDCDContext *ctx, int *peak_extend0, int *peak_extend1) |
|
|
|
|
static hdcd_control_result hdcd_control_stereo(HDCDContext *ctx, int *peak_extend0, int *peak_extend1) |
|
|
|
|
{ |
|
|
|
|
int target_gain[2]; |
|
|
|
|
hdcd_control(ctx, &ctx->state[0], peak_extend0, &target_gain[0]); |
|
|
|
@ -1476,7 +1476,7 @@ static hdcd_control_result_t hdcd_control_stereo(HDCDContext *ctx, int *peak_ext |
|
|
|
|
return HDCD_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void hdcd_process(HDCDContext *ctx, hdcd_state_t *state, int32_t *samples, int count, int stride) |
|
|
|
|
static void hdcd_process(HDCDContext *ctx, hdcd_state *state, int32_t *samples, int count, int stride) |
|
|
|
|
{ |
|
|
|
|
int32_t *samples_end = samples + count * stride; |
|
|
|
|
int gain = state->running_gain; |
|
|
|
@ -1582,7 +1582,7 @@ static void hdcd_process_stereo(HDCDContext *ctx, int32_t *samples, int count) |
|
|
|
|
ctx->state[1].running_gain = gain[1]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void hdcd_detect_reset(hdcd_detection_data_t *detect) { |
|
|
|
|
static void hdcd_detect_reset(hdcd_detection_data *detect) { |
|
|
|
|
detect->hdcd_detected = HDCD_NONE; |
|
|
|
|
detect->packet_type = HDCD_PVER_NONE; |
|
|
|
|
detect->total_packets = 0; |
|
|
|
@ -1594,15 +1594,15 @@ static void hdcd_detect_reset(hdcd_detection_data_t *detect) { |
|
|
|
|
detect->_active_count = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void hdcd_detect_start(hdcd_detection_data_t *detect) { |
|
|
|
|
static void hdcd_detect_start(hdcd_detection_data *detect) { |
|
|
|
|
detect->errors = 0; /* re-sum every pass */ |
|
|
|
|
detect->total_packets = 0; |
|
|
|
|
detect->_active_count = 0; /* will need to match channels at hdcd_detect_end() */ |
|
|
|
|
detect->cdt_expirations = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void hdcd_detect_onech(hdcd_state_t *state, hdcd_detection_data_t *detect) { |
|
|
|
|
hdcd_pe_t pe = HDCD_PE_NEVER; |
|
|
|
|
static void hdcd_detect_onech(hdcd_state *state, hdcd_detection_data *detect) { |
|
|
|
|
hdcd_pe pe = HDCD_PE_NEVER; |
|
|
|
|
detect->uses_transient_filter |= !!(state->count_transient_filter); |
|
|
|
|
detect->total_packets += state->code_counterA + state->code_counterB; |
|
|
|
|
if (state->code_counterA) detect->packet_type |= HDCD_PVER_A; |
|
|
|
@ -1627,7 +1627,7 @@ static void hdcd_detect_onech(hdcd_state_t *state, hdcd_detection_data_t *detect |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void hdcd_detect_end(hdcd_detection_data_t *detect, int channels) { |
|
|
|
|
static void hdcd_detect_end(hdcd_detection_data *detect, int channels) { |
|
|
|
|
/* HDCD is detected if a valid packet is active in all
|
|
|
|
|
* channels at the same time. */ |
|
|
|
|
if (detect->_active_count == channels) { |
|
|
|
@ -1740,7 +1740,7 @@ static av_cold void uninit(AVFilterContext *ctx) |
|
|
|
|
|
|
|
|
|
/* dump the state for each channel for AV_LOG_VERBOSE */ |
|
|
|
|
for (i = 0; i < HDCD_MAX_CHANNELS; i++) { |
|
|
|
|
hdcd_state_t *state = &s->state[i]; |
|
|
|
|
hdcd_state *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: pe: %d, tf: %d, almost_A: %d, checkfail_B: %d, unmatched_C: %d, cdt_expired: %d\n", i, |
|
|
|
|