?? block_encoder.cpp
字號(hào):
/* ========================================================================= *//*****************************************************************************//* kd_block_encoder::encode *//*****************************************************************************/void kd_block_encoder::encode(kdu_block *block, bool reversible, double msb_wmse, kdu_uint16 estimated_threshold){ double estimated_slope_threshold = -1.0; if ((estimated_threshold > 1) && (msb_wmse > 0.0) && (block->orientation != LL_BAND)) estimated_slope_threshold = slope_from_log(estimated_threshold); /* Note: the exclusion of the LL band above is important, since LL subband blocks do not generally have zero mean samples (far from it) so that an approximately uniform block can yield distortion which varies in an unpredictable manner with the number of coded bit-planes. These unpredictable variations can lead to a large number of consecutive coding passes not lying on the convex hull of the R-D curve -- a condition which would cause the coder to quit prematurely if an estimated slope threshold were given. */ /* Allocate space on the stack for a number of largish quantities. These could be placed elsewhere. */ double pass_wmse_changes[MAX_POSSIBLE_PASSES]; mq_encoder pass_encoders[MAX_POSSIBLE_PASSES]; 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_ENCODE_CWORDS; int num_context_words = (num_stripes+2)*context_row_gap+1; // Prepare enough storage. assert(block->max_samples >= num_samples); if (block->max_contexts < num_context_words) block->set_max_contexts((num_context_words > 1600)?num_context_words:1600); kdu_int32 *samples = block->sample_buffer; kdu_int32 *context_words = block->context_buffer + context_row_gap + 1; // Determine the actual number of passes which we can accomodate. if (block->num_passes > ((31-block->missing_msbs)*3-2)) block->num_passes = (31-block->missing_msbs)*3-2; // Make sure we have sufficient resources to process this number of passes if (block->max_passes < block->num_passes) block->set_max_passes(block->num_passes+10,false); // Allocate a few extra // Timing loop starts here. int cpu_counter = block->start_timing(); do { // Initialize contexts, marking OOB (Out Of Bounds) locations 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 unused 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 } double pass_wmse_scale = msb_wmse / ((double)(1<<16)) / ((double)(1<<16)); for (int i=block->missing_msbs; i > 0; i--) pass_wmse_scale *= 0.25; int p_max = 30 - block->missing_msbs; // Index of most significant plane 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_passes = 0; // Num coding passes in current codeword segment. kdu_byte *seg_buf = block->byte_buffer; // Start of current segment int segment_bytes = 0; // Bytes consumed so far by this codeword segment int first_unsized_z = 0; // First pass whose length is not yet known int available_bytes = block->max_bytes; // For current & future segments bool bypass = false; bool causal = (block->modes & Cmodes_CAUSAL) != 0; bool optimize = !(block->modes & Cmodes_ERTERM); for (; z < block->num_passes; z++, k++) { if (k == 3) { // Move on to next bit-plane. k=0; p--; pass_wmse_scale *= 0.25; } // See if we need to augment byte buffer resources to safely continue if ((available_bytes-segment_bytes) < 4096) { // We could build a much more thorough test for sufficiency. assert(available_bytes >= segment_bytes); // else already overrun kdu_byte *old_handle = block->byte_buffer; block->set_max_bytes(block->max_bytes+8192,true); available_bytes += 8192; kdu_byte *new_handle = block->byte_buffer; for (int i=0; i < z; i++) pass_encoders[i].augment_buffer(old_handle,new_handle); seg_buf = new_handle + (seg_buf-old_handle); } // Either start a new codeword segment, or continue an earlier one. if (segment_passes == 0) { // Need to start a new codeword segment. segment_passes = block->num_passes; 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; if ((z+segment_passes) > block->num_passes) segment_passes = block->num_passes - z; pass_encoders[z].start(seg_buf,!bypass); } else pass_encoders[z].continues(pass_encoders+z-1); // Encoding steps for the pass kdu_int32 distortion_change; bool lossless_pass = reversible && ((31-p) == block->K_max_prime); if ((z == 0) || (block->modes & Cmodes_RESET)) reset_states(); if ((k == 0) && !bypass) encode_sig_prop_pass(pass_encoders[z], states,p,causal,block->orientation, samples,context_words, num_cols,num_stripes,context_row_gap, lossless_pass); else if (k == 0) distortion_change = encode_sig_prop_pass_raw(pass_encoders[z], p,causal,samples,context_words, num_cols,num_stripes,context_row_gap, lossless_pass); else if ((k == 1) && !bypass) distortion_change = encode_mag_ref_pass(pass_encoders[z], states,p,causal,samples,context_words, num_cols,num_stripes,context_row_gap, lossless_pass); else if (k == 1) distortion_change = encode_mag_ref_pass_raw(pass_encoders[z], p,causal,samples,context_words, num_cols,num_stripes,context_row_gap, lossless_pass); else distortion_change = encode_cleanup_pass(pass_encoders[z], states,p,causal,block->orientation, samples,context_words, num_cols,num_stripes,context_row_gap, lossless_pass); pass_wmse_changes[z] = pass_wmse_scale * distortion_change; if ((block->modes & Cmodes_SEGMARK) && (k==2)) { kdu_int32 segmark = 0x0A; pass_encoders[z].mq_encode_run(segmark>>2); pass_encoders[z].mq_encode_run(segmark & 3); } // Update codeword segment status. segment_passes--; segment_bytes = pass_encoders[z].get_bytes_used(); if (segment_passes == 0) { kdu_byte *new_buf = pass_encoders[z].terminate(optimize); available_bytes -= (new_buf - seg_buf); seg_buf = new_buf; segment_bytes = 0; } { // Incrementally determine and process truncation lengths int t; bool final; for (t=first_unsized_z; t <= z; t++) { block->pass_lengths[t] = pass_encoders[t].get_incremental_length(final); if (final) { assert(first_unsized_z == t); first_unsized_z++; } } } if (estimated_slope_threshold > 0.0) { // See if we can finish up early to save time and memory. int t; for (t=z; (t >= 0) && (t > (z-3)); t--) { int delta_L = 0; double delta_D = 0.0; int u = 0; for (u=t; u >= 0; u--) { delta_L += block->pass_lengths[u]; delta_D += pass_wmse_changes[u]; if ((estimated_slope_threshold * delta_L) > delta_D) break; } if (u < 0) break; } if (t <= (z-3)) { block->num_passes = z+1; // No point in coding more passes. if (segment_passes > 0) { // Need to terminate the segment pass_encoders[z].terminate(optimize); for (t=first_unsized_z; t <= z; t++) { bool final; block->pass_lengths[t] = pass_encoders[t].get_incremental_length(final); assert(final); } first_unsized_z = t; segment_passes = 0; } } } if (segment_passes == 0) { // Finish cleaning up the completed codeword segment. assert(first_unsized_z == (z+1)); pass_encoders[z].finish(); } } assert(segment_passes == 0); assert(first_unsized_z == block->num_passes); if (msb_wmse > 0.0) { /* Form the convex hull set. We could have done most of the work incrementally as the lengths became available -- see above. However, there is little value to this in the present implementation. A hardware implementation may prefer the incremental calculation approach for all quantities, so that slopes and lengths can be dispatched in a covnenient interleaved fashion to memory as they become available. */ find_convex_hull(block->pass_lengths,pass_wmse_changes, block->pass_slopes,block->num_passes); if (reversible && ((31-p) == block->K_max_prime)) { /* Must force last coding pass onto convex hull. Otherwise, a decompressor using something other than the mid-point rounding rule can fail to achieve lossless decompression. */ z = block->num_passes-1; if (block->pass_slopes[z] == 0) block->pass_slopes[z] = 1; /* Works because `find_convex_hull_slopes' never generates slopes of 1. */ } } } while ((--cpu_counter) > 0); block->finish_timing();}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -