📄 block_decoder.cpp
字号:
row_0_significant: // Decode sign bit sym = cword & ((CHI_BIT>>3) | (SIGMA_CC_BIT>>3) | (CHI_BIT<<3) | (SIGMA_CC_BIT<<3)); sym >>= 1; // Shift down so that top sigma bit has address 0 sym |= (cp[-1] & ((CHI_BIT<<0) | (SIGMA_CC_BIT<<0))) >> (1+1); sym |= (cp[ 1] & ((CHI_BIT<<0) | (SIGMA_CC_BIT<<0))) >> (1-1); sym |= (sym >> (CHI_POS-1-SIGMA_CC_POS)); // Interleave chi & sigma val = sign_lut[sym & 0x000000FF]; state_ref = states + KAPPA_SIGN_BASE + (val>>1); _mq_dec_(coder,sym,*state_ref); sym ^= (val & 1); // Sign bit recovered in LSB. // Broadcast neighbourhood context changes if (!causal) { cp[-context_row_gap-1] |=(SIGMA_BR_BIT<<9); cp[-context_row_gap ] |=(SIGMA_BC_BIT<<9)|(sym<<NEXT_CHI_POS); cp[-context_row_gap+1] |=(SIGMA_BL_BIT<<9); } cp[-1] |= (SIGMA_CR_BIT<<0); cp[1] |= (SIGMA_CL_BIT<<0); cword |= (SIGMA_CC_BIT<<0) | (sym<<CHI_POS); sp[0] = (sym<<31) + one_point_five; }row_1: if (!(cword & (CLEANUP_MEMBER_MASK<<3))) { // Process second row of stripe column (row 1) state_ref = states+KAPPA_SIG_BASE+sig_lut[(cword>>3) & NBRHD_MASK]; _mq_dec_(coder,sym,*state_ref); if (!sym) goto row_2;row_1_significant: // Decode sign bit sym = cword & ((CHI_BIT<<0) | (SIGMA_CC_BIT<<0) | (CHI_BIT<<6) | (SIGMA_CC_BIT<<6)); sym >>= 4; // Shift down so that top sigma bit has address 0 sym |= (cp[-1] & ((CHI_BIT<<3) | (SIGMA_CC_BIT<<3))) >> (4+1); sym |= (cp[ 1] & ((CHI_BIT<<3) | (SIGMA_CC_BIT<<3))) >> (4-1); sym |= (sym >> (CHI_POS-1-SIGMA_CC_POS)); // Interleave chi & sigma val = sign_lut[sym & 0x000000FF]; state_ref = states + KAPPA_SIGN_BASE + (val>>1); _mq_dec_(coder,sym,*state_ref); sym ^= (val & 1); // Sign bit recovered in LSB. // Broadcast neighbourhood context changes cp[-1] |= (SIGMA_CR_BIT<<3); cp[1] |= (SIGMA_CL_BIT<<3); cword |= (SIGMA_CC_BIT<<3) | (sym<<(CHI_POS+3)); sp[width] = (sym<<31) + one_point_five; }row_2: if (!(cword & (CLEANUP_MEMBER_MASK<<6))) { // Process third row of stripe column (row 2) state_ref = states+KAPPA_SIG_BASE+sig_lut[(cword>>6) & NBRHD_MASK]; _mq_dec_(coder,sym,*state_ref); if (!sym) goto row_3;row_2_significant: // Decode sign bit sym = cword & ((CHI_BIT<<3) | (SIGMA_CC_BIT<<3) | (CHI_BIT<<9) | (SIGMA_CC_BIT<<9)); sym >>= 7; // Shift down so that top sigma bit has address 0 sym |= (cp[-1] & ((CHI_BIT<<6) | (SIGMA_CC_BIT<<6))) >> (7+1); sym |= (cp[ 1] & ((CHI_BIT<<6) | (SIGMA_CC_BIT<<6))) >> (7-1); sym |= (sym >> (CHI_POS-1-SIGMA_CC_POS)); // Interleave chi & sigma val = sign_lut[sym & 0x000000FF]; state_ref = states + KAPPA_SIGN_BASE + (val>>1); _mq_dec_(coder,sym,*state_ref); sym ^= (val & 1); // Sign bit recovered in LSB. // Broadcast neighbourhood context changes cp[-1] |= (SIGMA_CR_BIT<<6); cp[1] |= (SIGMA_CL_BIT<<6); cword |= (SIGMA_CC_BIT<<6) | (sym << (CHI_POS+6)); sp[width_by2] = (sym<<31) + one_point_five; }row_3: if (!(cword & (CLEANUP_MEMBER_MASK<<9))) { // Process fourth row of stripe column (row 3) state_ref = states+KAPPA_SIG_BASE+sig_lut[(cword>>9) & NBRHD_MASK]; _mq_dec_(coder,sym,*state_ref); if (!sym) goto done;row_3_significant: // Decode sign bit sym = cword & ((CHI_BIT<<6) | (SIGMA_CC_BIT<<6) | 0 | (SIGMA_CC_BIT<<12)); sym >>= 10; // Shift down so that top sigma bit has address 0 if (cword < 0) // Use the fact that NEXT_CHI_BIT = 31 sym |= CHI_BIT<<(12-10); sym |= (cp[-1] & ((CHI_BIT<<9) | (SIGMA_CC_BIT<<9))) >> (10+1); sym |= (cp[ 1] & ((CHI_BIT<<9) | (SIGMA_CC_BIT<<9))) >> (10-1); sym |= (sym >> (CHI_POS-1-SIGMA_CC_POS)); // Interleave chi & sigma val = sign_lut[sym & 0x000000FF]; state_ref = states + KAPPA_SIGN_BASE + (val>>1); _mq_dec_(coder,sym,*state_ref); sym ^= (val & 1); // Sign bit recovered in LSB. // Broadcast neighbourhood context changes cp[context_row_gap-1] |= SIGMA_TR_BIT; cp[context_row_gap ] |= SIGMA_TC_BIT | (sym<<PREV_CHI_POS); cp[context_row_gap+1] |= SIGMA_TL_BIT; cp[-1] |= (SIGMA_CR_BIT<<9); cp[1] |= (SIGMA_CL_BIT<<9); cword |= (SIGMA_CC_BIT<<9) | (sym<<(CHI_POS+9)); sp[width_by3] = (sym<<31) + one_point_five; }done: cword |= (cword << (MU_POS - SIGMA_CC_POS)) & ((MU_BIT<<0)|(MU_BIT<<3)|(MU_BIT<<6)|(MU_BIT<<9)); cword &= ~((PI_BIT<<0)|(PI_BIT<<3)|(PI_BIT<<6)|(PI_BIT<<9)); *cp = cword; } states[KAPPA_RUN_BASE] = run_state; _mq_check_in_(coder);}/* ========================================================================= *//* kdu_block_decoder *//* ========================================================================= *//*****************************************************************************//* kdu_block_decoder::kdu_block_decoder *//*****************************************************************************/kdu_block_decoder::kdu_block_decoder(){ state = new kd_block_decoder;}/* ========================================================================= *//* kd_block_decoder *//* ========================================================================= *//*****************************************************************************//* kd_block_decoder::decode *//*****************************************************************************/void kd_block_decoder::decode(kdu_block *block){ // Get dimensions. int num_cols = block->size.x; int num_rows = block->size.y; int num_stripes = (num_rows+3)>>2; int num_samples = (num_stripes<<2)*num_cols; int context_row_gap = num_cols + EXTRA_DECODE_CWORDS; int num_context_words = (num_stripes+2)*context_row_gap+1; // Prepare enough storage. if (block->max_samples < num_samples) block->set_max_samples((num_samples > 4096)?num_samples:4096); if (block->max_contexts < num_context_words) block->set_max_contexts((num_context_words > 1600)?num_context_words:1600); // Start timing loop here, if there is any need for one. int cpu_counter = block->start_timing(); bool error_found; do { error_found = false; // Initialize sample and context word contents kdu_int32 *samples = block->sample_buffer; memset(samples,0,(size_t)(num_samples<<2)); kdu_int32 *context_words = block->context_buffer + context_row_gap + 1; memset(context_words-1,0,(size_t)((num_stripes*context_row_gap+1)<<2)); if (num_rows & 3) { kdu_int32 oob_marker; if ((num_rows & 3) == 1) // Last 3 rows of last stripe unoccupied oob_marker = (OOB_MARKER<<3) | (OOB_MARKER<<6) | (OOB_MARKER<<9); else if ((num_rows & 3) == 2) // Last 2 rows of last stripe are empty oob_marker = (OOB_MARKER << 6) | (OOB_MARKER << 9); else oob_marker = (OOB_MARKER << 9); kdu_int32 *cp = context_words + (num_stripes-1)*context_row_gap; for (int k=num_cols; k > 0; k--) *(cp++) = oob_marker; } if (context_row_gap > num_cols) { // Initialize the extra context words between lines to OOB kdu_int32 oob_marker = OOB_MARKER | (OOB_MARKER<<3) | (OOB_MARKER<<6) | (OOB_MARKER<<9); assert(context_row_gap >= (num_cols+3)); kdu_int32 *cp = context_words + num_cols; for (int k=num_stripes; k > 0; k--, cp+=context_row_gap) cp[0] = cp[1] = cp[2] = oob_marker; // Need 3 OOB words after line } // Determine which passes we can decode and where to put them. int p_max = 30 - block->missing_msbs; // Index of most significant plane int num_passes = 3*p_max-2; // 1 plane for dequantization signalling if (num_passes > block->num_passes) num_passes = block->num_passes; // Now decode the passes one by one. int p = p_max; // Bit-plane counter int z = 0; // Coding pass index int k=2; // Coding pass category; start with cleanup pass int segment_start_z; int segment_passes = 0; // Num coding passes in current codeword segment. bool segment_truncated = false; int segment_bytes = 0; kdu_byte *buf = block->byte_buffer; bool bypass = false; bool causal = (block->modes & Cmodes_CAUSAL) != 0; bool er_check = (block->modes & Cmodes_ERTERM) && (block->fussy || block->resilient); for (; z < num_passes; z++, k++) { if (k == 3) { k=0; p--; } // Move on to next bit-plane. if (segment_passes == 0) { // Need to start a new codeword segment. segment_start_z = z; segment_passes = 3*(block->K_max_prime-block->missing_msbs) - 2; if (block->modes & Cmodes_BYPASS) { if (z < 10) segment_passes = 10-z; else if (k == 2) // Cleanup pass. { segment_passes = 1; bypass = false; } else { segment_passes = 2; bypass = true; } } if (block->modes & Cmodes_RESTART) segment_passes = 1; segment_truncated = false; if ((z+segment_passes) > num_passes) { segment_truncated = true; segment_passes = num_passes - z; } segment_bytes = 0; for (int n=0; n < segment_passes; n++) segment_bytes += block->pass_lengths[z+n]; coder.start(buf,segment_bytes,!bypass); buf += segment_bytes; } if ((z == 0) || (block->modes & Cmodes_RESET)) reset_states();#ifdef KDU_ASM_OPTIMIZATIONS if (mmx_exists) { // Invoke highly optimized machine-specific forms where available if ((k == 0) && !bypass) asm_decode_sig_prop_pass(coder,states,p,causal, block->orientation,samples,context_words, num_cols,num_stripes,context_row_gap); else if (k == 0) decode_sig_prop_pass_raw(coder,p,causal,samples, context_words,num_cols,num_stripes,context_row_gap); else if ((k == 1) && !bypass) asm_decode_mag_ref_pass(coder,states,p,causal,samples, context_words,num_cols,num_stripes,context_row_gap); else if (k == 1) decode_mag_ref_pass_raw(coder,p,causal,samples, context_words,num_cols,num_stripes,context_row_gap); else asm_decode_cleanup_pass(coder,states,p,causal, block->orientation,samples,context_words, num_cols,num_stripes,context_row_gap); } else#endif // KDU_ASM_OPTIMIZATIONS if ((k == 0) && !bypass) decode_sig_prop_pass(coder,states,p,causal, block->orientation,samples,context_words, num_cols,num_stripes,context_row_gap); else if (k == 0) decode_sig_prop_pass_raw(coder,p,causal,samples, context_words,num_cols,num_stripes,context_row_gap); else if ((k == 1) && !bypass) decode_mag_ref_pass(coder,states,p,causal,samples, context_words,num_cols,num_stripes,context_row_gap); else if (k == 1) decode_mag_ref_pass_raw(coder,p,causal,samples, context_words,num_cols,num_stripes,context_row_gap); else decode_cleanup_pass(coder,states,p,causal, block->orientation,samples,context_words, num_cols,num_stripes,context_row_gap); if ((block->modes & Cmodes_SEGMARK) && (k==2)) { kdu_int32 run, segmark; coder.mq_decode_run(run); segmark = run<<2; coder.mq_decode_run(run); segmark += run; if ((segmark != 0x0A) && (block->fussy || block->resilient)) { // Segmark not detected correctly. error_found = true; block->num_passes = (z > 2)?(z-2):0; break; } } segment_passes--; if (segment_passes == 0) { if (!coder.finish(er_check && !segment_truncated)) { // Error has been detected in the current codeword segment. error_found = true; block->num_passes = segment_start_z; break; } } } if (error_found) { if (block->fussy) { kdu_error e; e << "Encountered incorrectly terminated codeword " "segment, or invalid SEGMARK symbol in code-block bit-stream. " "You may like to use the \"resilient\" mode to recover from " "and conceal such errors."; } else { kdu_warning w; w << "Corrupted block bit-stream detected.\n"; } } } while (error_found || ((--cpu_counter) > 0)); block->finish_timing();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -