summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavfilter/af_hdcd.c86
1 files changed, 60 insertions, 26 deletions
diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c
index 8e27d8aee8..0752c39555 100644
--- a/libavfilter/af_hdcd.c
+++ b/libavfilter/af_hdcd.c
@@ -933,6 +933,45 @@ static void hdcd_update_info(hdcd_state_t *state)
state->max_gain = FFMAX(state->max_gain, (state->control & 15));
}
+typedef enum {
+ HDCD_CODE_NONE=0,
+ HDCD_CODE_A,
+ HDCD_CODE_A_ALMOST,
+ HDCD_CODE_B,
+ HDCD_CODE_B_CHECKFAIL,
+ HDCD_CODE_EXPECT_A,
+ HDCD_CODE_EXPECT_B,
+} hdcd_code_result_t;
+
+static hdcd_code_result_t hdcd_code(const uint32_t bits, unsigned char *code)
+{
+ if ((bits & 0x0fa00500) == 0x0fa00500) {
+ /* A: 8-bit code 0x7e0fa005[..] */
+ if ((bits & 0xc8) == 0) {
+ /* [..pt gggg]
+ * 0x0fa005[..] -> 0b[00.. 0...], gain part doubled */
+ *code = (bits & 255) + (bits & 7);
+ return HDCD_CODE_A;
+ } else
+ return HDCD_CODE_A_ALMOST; /* one of bits 3, 6, or 7 was not 0 */
+ } else if ((bits & 0xa0060000) == 0xa0060000) {
+ /* B: 8-bit code, 8-bit XOR check, 0x7e0fa006[....] */
+ if (((bits ^ (~bits >> 8 & 255)) & 0xffff00ff) == 0xa0060000) {
+ /* check: [..pt gggg ~(..pt gggg)]
+ * 0xa006[....] -> 0b[.... .... .... .... ] */
+ *code = bits >> 8 & 255;
+ return HDCD_CODE_B;
+ } else
+ return HDCD_CODE_B_CHECKFAIL; /* XOR check failed */
+ }
+ if (bits == 0x7e0fa005)
+ return HDCD_CODE_EXPECT_A;
+ else if (bits == 0x7e0fa006)
+ return HDCD_CODE_EXPECT_B;
+
+ return HDCD_CODE_NONE;
+}
+
static int hdcd_integrate(HDCDContext *ctx, hdcd_state_t *state, int *flag, const int32_t *samples, int count, int stride)
{
uint32_t bits = 0;
@@ -953,44 +992,39 @@ static int hdcd_integrate(HDCDContext *ctx, hdcd_state_t *state, int *flag, cons
bits = (state->window ^ state->window >> 5 ^ state->window >> 23);
if (state->arg) {
- if ((bits & 0x0fa00500) == 0x0fa00500) {
- /* A: 8-bit code */
- if ((bits & 0xc8) == 0) {
- /* [..pt gggg]
- * 0x0fa005[..] -> 0b[00.. 0...], gain part doubled */
- state->control = (bits & 255) + (bits & 7);
+ switch (hdcd_code(bits, &state->control)) {
+ case HDCD_CODE_A:
*flag = 1;
state->code_counterA++;
- } else {
- /* one of bits 3, 6, or 7 was not 0 */
+ break;
+ case HDCD_CODE_B:
+ *flag = 1;
+ state->code_counterB++;
+ break;
+ case HDCD_CODE_A_ALMOST:
state->code_counterA_almost++;
av_log(ctx->fctx, AV_LOG_VERBOSE,
"hdcd error: Control A almost: 0x%02x near %d\n", bits & 0xff, ctx->sample_count);
- }
- } else if ((bits & 0xa0060000) == 0xa0060000) {
- /* B: 8-bit code, 8-bit XOR check */
- if (((bits ^ (~bits >> 8 & 255)) & 0xffff00ff) == 0xa0060000) {
- /* check: [..pt gggg ~(..pt gggg)]
- * 0xa006[....] -> 0b[.... .... .... .... ] */
- state->control = bits >> 8 & 255;
- *flag = 1;
- state->code_counterB++;
- } else {
- /* XOR check failed */
+ break;
+ case HDCD_CODE_B_CHECKFAIL:
state->code_counterB_checkfails++;
av_log(ctx->fctx, AV_LOG_VERBOSE,
- "hdcd error: Control B check failed: 0x%04x (0x%02x vs 0x%02x) near %d\n", bits & 0xffff, (bits & 0xff00) >> 8, ~bits & 0xff, ctx->sample_count);
- }
- } else {
- /* told to look for a code, but didn't match one */
- state->code_counterC_unmatched++;
- av_log(ctx->fctx, AV_LOG_VERBOSE,
- "hdcd error: Unmatched code: 0x%08x near %d\n", bits, ctx->sample_count);
+ "hdcd error: Control B check failed: 0x%04x (0x%02x vs 0x%02x) near %d\n", bits & 0xffff, (bits & 0xff00) >> 8, ~bits & 0xff, ctx->sample_count);
+ break;
+ case HDCD_CODE_NONE:
+ state->code_counterC_unmatched++;
+ av_log(ctx->fctx, AV_LOG_VERBOSE,
+ "hdcd error: Unmatched code: 0x%08x near %d\n", bits, ctx->sample_count);
+ default:
+ av_log(ctx->fctx, AV_LOG_INFO,
+ "hdcd error: Unexpected return value from hdcd_code()\n");
+ av_assert0(0); /* die */
}
if (*flag) hdcd_update_info(state);
state->arg = 0;
}
if (bits == 0x7e0fa005 || bits == 0x7e0fa006) {
+ /* 0x7e0fa00[.]-> [0b0101 or 0b0110] */
state->readahead = (bits & 3) * 8;
state->arg = 1;
state->code_counterC++;