From patchwork Sun Oct 2 07:46:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Burt P X-Patchwork-Id: 824 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.66 with SMTP id o63csp1039290vsd; Sun, 2 Oct 2016 00:47:08 -0700 (PDT) X-Received: by 10.28.186.6 with SMTP id k6mr598195wmf.101.1475394428008; Sun, 02 Oct 2016 00:47:08 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id jg8si29343485wjb.4.2016.10.02.00.47.07; Sun, 02 Oct 2016 00:47:07 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E70EF68A0E6; Sun, 2 Oct 2016 10:46:38 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-it0-f67.google.com (mail-it0-f67.google.com [209.85.214.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C8FC5689E9C for ; Sun, 2 Oct 2016 10:46:31 +0300 (EEST) Received: by mail-it0-f67.google.com with SMTP id l13so5417503itl.2 for ; Sun, 02 Oct 2016 00:46:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=EyjuU43gyvpPBW/sOl7LHC5dZWUs/26UvT1vCOjoSJo=; b=hClWa9jGYYFSQ9Zov9Rtq8wynEBEVWOeOxTiLXRzj1N5nyEs2rzAAWkwKRVqfWVhQx hPAl5JaVo/tspaWoZJaJKGhLTeTok71XgJAZ743hlu/5r/qdPqXEphm17JwiXGyDl4xE Oot3G077zVM3+9RStjllmywQJui9DVvOT0XwMwvdlf6cfIh1mI3CrNIxHHst4XdlB3wg /Tnjb5yA8fGfJWE/a2K7Yt+FsklID4t0l/Xvp0giO6vkU4NSc9LbM8AnIUY0CF52cJhj SuS85SxiXs6jWV58t5uLHbx/Edvxo5uBLqt0V+Z/J7k45PC3mCza98nwrFBh6nhJzURW vebg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=EyjuU43gyvpPBW/sOl7LHC5dZWUs/26UvT1vCOjoSJo=; b=OLXxA/Td/1CYjrefXsPQId5H3Al2vV1hHCDbss8DdWFkZsywP5zBsg/0g0YzfDBj11 5/Tm4yF3M1OtrKm0/dUCo+HQ3/K+6NO5PumFlMw/Mb2ZfBr1C2j4Q1ml8nZ47KwT/m0W 0eUuUT2dq6BT4F5tQUcT8CPuiWf+40M8qP5NFU/CpFr+7CcNwKC9hAdYe63Jg0V61BpM VvQGd4Za2JWneujmRrkJjYiKVYrjt1sbgKXSEsX7C1nCi0rZPdF+bMwFCmFWD1GWh1XQ U94dGv8YW6/8UQEMiUyXIPizFtG9/Pb84AYepvGlyb9sYz68jrcJDEZ4iW3SKo0Fov7p Yn3Q== X-Gm-Message-State: AA6/9RmBbIdzRtL/PEAJuguG05DTcfOLn2r5NIKcNKjHN7Hu7ld7LuLnLmcvkAoCpLtkAw== X-Received: by 10.36.222.137 with SMTP id d131mr11588771itg.1.1475394404272; Sun, 02 Oct 2016 00:46:44 -0700 (PDT) Received: from localhost.localdomain ([216.16.66.181]) by smtp.gmail.com with ESMTPSA id s185sm5387725ita.21.2016.10.02.00.46.43 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 02 Oct 2016 00:46:43 -0700 (PDT) From: Burt P To: ffmpeg-devel@ffmpeg.org Date: Sun, 2 Oct 2016 02:46:32 -0500 Message-Id: <1475394393-10173-5-git-send-email-pburt0@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1475394393-10173-1-git-send-email-pburt0@gmail.com> References: <1475394393-10173-1-git-send-email-pburt0@gmail.com> Subject: [FFmpeg-devel] [PATCH 4/5] af_hdcd: hdcd_scan() and hdcd_integrate() handle stereo and single channel X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" New versions of hdcd_scan() and hdcd_integrate() that also do the work of hdcd_scan_stereo() and hdcd_integrate_stereo(). Some code split into previously separate functions to remove duplication is now merged back into each function in the single place where it is used. Signed-off-by: Burt P --- libavfilter/af_hdcd.c | 303 ++++++++++++++------------------------------------ 1 file changed, 85 insertions(+), 218 deletions(-) diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c index 6f35c09..b5aad85 100644 --- a/libavfilter/af_hdcd.c +++ b/libavfilter/af_hdcd.c @@ -1031,267 +1031,134 @@ static void hdcd_reset(hdcd_state *state, unsigned rate, unsigned cdt_ms) state->_ana_snb = 0; } -/** update the user info/counters */ -static void hdcd_update_info(hdcd_state *state) +static int hdcd_integrate(HDCDContext *ctx, hdcd_state *states, int channels, int *flag, const int32_t *samples, int count, int stride) { - 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)); -} - -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; - -static hdcd_code_result 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 *state, int *flag, const int32_t *samples, int count, int stride) -{ - uint32_t bits = 0; - int result = FFMIN(state->readahead, count); - int i; + uint32_t bits[HDCD_MAX_CHANNELS]; + int result = count; + int i, j, f; *flag = 0; - for (i = result - 1; i >= 0; i--) { - bits |= (*samples & 1) << i; /* might be better as a conditional? */ - samples += stride; - } + memset(bits, 0, sizeof(bits)); + if (stride < channels) stride = channels; - state->window = (state->window << result) | bits; - state->readahead -= result; - if (state->readahead > 0) - return result; + for (i = 0; i < channels; i++) + result = FFMIN(states[i].readahead, result); - bits = (state->window ^ state->window >> 5 ^ state->window >> 23); - - if (state->arg) { - switch (hdcd_code(bits, &state->control)) { - case HDCD_CODE_A: - *flag = 1; - state->code_counterA++; - 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); - 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); - 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; + for (j = result - 1; j >= 0; j--) { + for (i = 0; i < channels; i++) + bits[i] |= (*(samples++) & 1) << j; + samples += stride - channels; } - if (bits == 0x7e0fa005 || bits == 0x7e0fa006) { - /* 0x7e0fa00[.]-> [0b0101 or 0b0110] */ - state->readahead = (bits & 3) * 8; - state->arg = 1; - state->code_counterC++; - } else { - if (bits) - state->readahead = readaheadtab[bits & 0xff]; - else - state->readahead = 31; /* ffwd over digisilence */ - } - return result; -} - -static int hdcd_integrate_stereo(HDCDContext *ctx, int *flag, const int32_t *samples, int count) -{ - uint32_t bits[2] = {0, 0}; - int result; - int i; - *flag = 0; - - /* result = min(count, s0ra, s1ra) */ - result = FFMIN(ctx->state[0].readahead, count); - result = FFMIN(ctx->state[1].readahead, result); - for (i = result - 1; i >= 0; i--) { - bits[0] |= (*(samples++) & 1) << i; - bits[1] |= (*(samples++) & 1) << i; - } - - for (i = 0; i < 2; i++) { - ctx->state[i].window = (ctx->state[i].window << result) | bits[i]; - ctx->state[i].readahead -= result; - - if (ctx->state[i].readahead == 0) { - uint32_t wbits = (ctx->state[i].window ^ ctx->state[i].window >> 5 ^ ctx->state[i].window >> 23); - if (ctx->state[i].arg) { - switch (hdcd_code(wbits, &ctx->state[i].control)) { - case HDCD_CODE_A: - *flag |= i+1; - ctx->state[i].code_counterA++; - break; - case HDCD_CODE_B: - *flag |= i+1; - ctx->state[i].code_counterB++; - break; - case HDCD_CODE_A_ALMOST: - ctx->state[i].code_counterA_almost++; + for (i = 0; i < channels; i++) { + states[i].window = (states[i].window << result) | bits[i]; + states[i].readahead -= result; + + if (states[i].readahead == 0) { + uint32_t wbits = (uint32_t)(states[i].window ^ states[i].window >> 5 ^ states[i].window >> 23); + if (states[i].arg) { + f = 0; + if ((wbits & 0x0fa00500) == 0x0fa00500) { + /* A: 8-bit code 0x7e0fa005[..] */ + if ((wbits & 0xc8) == 0) { + /* [..pt gggg] + * 0x0fa005[..] -> 0b[00.. 0...], gain part doubled (shifted left 1) */ + states[i].control = (wbits & 255) + (wbits & 7); + f = 1; + states[i].code_counterA++; + } else { + /* one of bits 3, 6, or 7 was not 0 */ + states[i].code_counterA_almost++; av_log(ctx->fctx, AV_LOG_VERBOSE, "hdcd error: Control A almost: 0x%02x near %d\n", wbits & 0xff, ctx->sample_count); - break; - case HDCD_CODE_B_CHECKFAIL: - ctx->state[i].code_counterB_checkfails++; + } + } else if ((wbits & 0xa0060000) == 0xa0060000) { + /* B: 8-bit code, 8-bit XOR check, 0x7e0fa006[....] */ + if (((wbits ^ (~wbits >> 8 & 255)) & 0xffff00ff) == 0xa0060000) { + /* check: [..pt gggg ~(..pt gggg)] + * 0xa006[....] -> 0b[.... .... .... .... ] */ + states[i].control = wbits >> 8 & 255; + f = 1; + states[i].code_counterB++; + } else { + /* XOR check failed */ + states[i].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", wbits & 0xffff, (wbits & 0xff00) >> 8, ~wbits & 0xff, ctx->sample_count); - break; - case HDCD_CODE_NONE: - ctx->state[i].code_counterC_unmatched++; - av_log(ctx->fctx, AV_LOG_VERBOSE, - "hdcd error: Unmatched code: 0x%08x near %d\n", wbits, 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 (f) { + *flag |= (1<state[i]); - ctx->state[i].arg = 0; + states[i].arg = 0; } if (wbits == 0x7e0fa005 || wbits == 0x7e0fa006) { /* 0x7e0fa00[.]-> [0b0101 or 0b0110] */ - ctx->state[i].readahead = (wbits & 3) * 8; - ctx->state[i].arg = 1; - ctx->state[i].code_counterC++; + states[i].readahead = (wbits & 3) * 8; + states[i].arg = 1; + states[i].code_counterC++; } else { if (wbits) - ctx->state[i].readahead = readaheadtab[wbits & 0xff]; + states[i].readahead = readaheadtab[wbits & 0xff]; else - ctx->state[i].readahead = 31; /* ffwd over digisilence */ + states[i].readahead = 31; /* ffwd over digisilence */ } } } return result; } -static void hdcd_sustain_reset(hdcd_state *state) -{ - state->sustain = state->sustain_reset; - /* if this is the first reset then change - * from never set, to never expired */ - if (state->count_sustain_expired == -1) - state->count_sustain_expired = 0; -} - -static int hdcd_scan(HDCDContext *ctx, hdcd_state *state, const int32_t *samples, int max, int stride) -{ - int result; - int cdt_active = 0; - /* code detect timer */ - if (state->sustain > 0) { - cdt_active = 1; - if (state->sustain <= max) { - state->control = 0; - max = state->sustain; - } - state->sustain -= max; - } - - result = 0; - while (result < max) { - int flag; - int consumed = hdcd_integrate(ctx, state, &flag, samples, max - result, stride); - result += consumed; - if (flag > 0) { - /* reset timer if code detected in channel */ - hdcd_sustain_reset(state); - break; - } - samples += consumed * stride; - } - /* code detect timer expired */ - if (cdt_active && state->sustain == 0) - state->count_sustain_expired++; - - return result; -} - -static int hdcd_scan_stereo(HDCDContext *ctx, const int32_t *samples, int max) +static int hdcd_scan(HDCDContext *ctx, hdcd_state *states, int channels, const int32_t *samples, int max, int stride) { int result; int i; - int cdt_active[2] = {0, 0}; + int cdt_active[HDCD_MAX_CHANNELS]; + memset(cdt_active, 0, sizeof(cdt_active)); + + if (stride < channels) stride = channels; /* code detect timers for each channel */ - for(i=0; i<2; i++) { - if (ctx->state[i].sustain > 0) { + for(i = 0; i < channels; i++) { + if (states[i].sustain > 0) { cdt_active[i] = 1; - if (ctx->state[i].sustain <= max) { - ctx->state[i].control = 0; - max = ctx->state[i].sustain; + if (states[i].sustain <= (unsigned)max) { + states[i].control = 0; + max = states[i].sustain; } - ctx->state[i].sustain -= max; + states[i].sustain -= max; } } result = 0; while (result < max) { int flag; - int consumed = hdcd_integrate_stereo(ctx, &flag, samples, max - result); + int consumed = hdcd_integrate(ctx, states, channels, &flag, samples, max - result, stride); result += consumed; if (flag) { /* reset timer if code detected in a channel */ - if (flag & 1) hdcd_sustain_reset(&ctx->state[0]); - if (flag & 2) hdcd_sustain_reset(&ctx->state[1]); + for(i = 0; i < channels; i++) { + if (flag & (1<state[i].sustain == 0) - ctx->state[i].count_sustain_expired++; + if (cdt_active[i] && states[i].sustain == 0) + states[i].count_sustain_expired++; } return result; @@ -1496,7 +1363,7 @@ static void hdcd_process(HDCDContext *ctx, hdcd_state *state, int32_t *samples, int run; av_assert0(samples + lead * stride + stride * (count - lead) <= samples_end); - run = hdcd_scan(ctx, state, samples + lead * stride, count - lead, stride) + lead; + run = hdcd_scan(ctx, state, 1, samples + lead * stride, count - lead, 0) + lead; envelope_run = run - 1; av_assert0(samples + envelope_run * stride <= samples_end); @@ -1540,7 +1407,7 @@ static void hdcd_process_stereo(HDCDContext *ctx, int32_t *samples, int count) int envelope_run, run; av_assert0(samples + lead * stride + stride * (count - lead) <= samples_end); - run = hdcd_scan_stereo(ctx, samples + lead * stride, count - lead) + lead; + run = hdcd_scan(ctx, ctx->state, 2, samples + lead * stride, count - lead, 0) + lead; envelope_run = run - 1; av_assert0(samples + envelope_run * stride <= samples_end);