diff --git a/src/encmain.c b/src/encmain.c index 22bbd9ab..110b1ec4 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -299,6 +299,8 @@ int main(int argc, char *argv[]) // TODO: Add config option for vps_period. encoder.vps_period = (encoder.cfg->rdo == 0 ? encoder.cfg->intra_period : 0); + encoder.sign_hiding = ENABLE_SIGN_HIDING; + encoder.in.file = input; fprintf(stderr, "Input: %s, output: %s\n", cfg->input, cfg->output); diff --git a/src/encoder.h b/src/encoder.h index 64975128..bbd3b30e 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -145,6 +145,8 @@ typedef struct encoder_control // How often Video Parameter Set is re-sent. uint32_t vps_period; + bool sign_hiding; + } encoder_control; int encoder_control_init(encoder_control *encoder, const config *cfg); diff --git a/src/encoder_state-bitstream.c b/src/encoder_state-bitstream.c index 8db404d2..7bad9867 100644 --- a/src/encoder_state-bitstream.c +++ b/src/encoder_state-bitstream.c @@ -394,7 +394,7 @@ static void encoder_state_write_bitstream_pic_parameter_set(encoder_state * cons WRITE_U(stream, 0, 1, "dependent_slice_segments_enabled_flag"); WRITE_U(stream, 0, 1, "output_flag_present_flag"); WRITE_U(stream, 0, 3, "num_extra_slice_header_bits"); - WRITE_U(stream, ENABLE_SIGN_HIDING, 1, "sign_data_hiding_flag"); + WRITE_U(stream, encoder->sign_hiding, 1, "sign_data_hiding_flag"); WRITE_U(stream, 0, 1, "cabac_init_present_flag"); WRITE_UE(stream, 0, "num_ref_idx_l0_default_active_minus1"); diff --git a/src/encoderstate.c b/src/encoderstate.c index bc219666..c2bd0f22 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -1572,7 +1572,7 @@ void encode_coeff_nxn(encoder_state * const encoder_state, coefficient *coeff, u int32_t scan_pos_last = -1; int32_t pos_last = 0; int32_t shift = 4>>1; - int8_t be_valid = ENABLE_SIGN_HIDING; + int8_t be_valid = encoder->sign_hiding; int32_t scan_pos_sig; int32_t last_scan_set; uint32_t go_rice_param = 0; diff --git a/src/rdo.c b/src/rdo.c index 19034ad9..2e2fd904 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -434,6 +434,113 @@ static void calc_last_bits(encoder_state * const encoder_state, int32_t width, i last_y_bits[ctx] = bits_y; } +void rdoq_sign_hiding(const encoder_state *const encoder_state, + const int32_t qp_scaled, + const uint32_t *const scan, + const int32_t delta_u[32 * 32], + const int32_t rate_inc_up[32 * 32], + const int32_t rate_inc_down[32 * 32], + const int32_t sig_rate_delta[32 * 32], + const int32_t width, + const coefficient *const coef, + coefficient *const dest_coeff) +{ + const encoder_control * const encoder = encoder_state->encoder_control; + const int32_t size = width * width; + + int64_t rd_factor = (int64_t)( + g_inv_quant_scales[qp_scaled % 6] * g_inv_quant_scales[qp_scaled % 6] * (1 << (2 * (qp_scaled / 6))) + / encoder_state->global->cur_lambda_cost / 16 / (1 << (2 * (encoder->bitdepth - 8))) + + 0.5); + int32_t lastCG = -1; + int32_t absSum = 0; + int32_t n, subset; + + for (subset = (size - 1) >> LOG2_SCAN_SET_SIZE; subset >= 0; subset--) { + int32_t subPos = subset << LOG2_SCAN_SET_SIZE; + int32_t firstNZPosInCG = SCAN_SET_SIZE, lastNZPosInCG = -1; + absSum = 0; + + for (n = SCAN_SET_SIZE - 1; n >= 0; --n) { + if (dest_coeff[scan[n + subPos]]) { + lastNZPosInCG = n; + break; + } + } + + for (n = 0; n = 0 && lastCG == -1) lastCG = 1; + + if (lastNZPosInCG - firstNZPosInCG >= SBH_THRESHOLD) { + int32_t signbit = (dest_coeff[scan[subPos + firstNZPosInCG]]>0 ? 0 : 1); + if (signbit != (absSum & 0x1)) { // hide but need tune + // calculate the cost + int64_t minCostInc = MAX_INT64, curCost = MAX_INT64; + int32_t minPos = -1, finalChange = 0, curChange = 0; + + for (n = (lastCG == 1 ? lastNZPosInCG : SCAN_SET_SIZE - 1); n >= 0; --n) { + uint32_t blkpos = scan[n + subPos]; + if (dest_coeff[blkpos] != 0) { + int64_t costUp = rd_factor * (-delta_u[blkpos]) + rate_inc_up[blkpos]; + int64_t costDown = rd_factor * (delta_u[blkpos]) + rate_inc_down[blkpos] + - (abs(dest_coeff[blkpos]) == 1 ? ((1 << 15) + sig_rate_delta[blkpos]) : 0); + + if (lastCG == 1 && lastNZPosInCG == n && abs(dest_coeff[blkpos]) == 1) { + costDown -= (4 << 15); + } + + if (costUp= 0) ? 0 : 1) != signbit) curCost = MAX_INT64; + } + } + + if (curCost= 0) { + dest_coeff[minPos] += (coefficient)finalChange; + } else { + dest_coeff[minPos] -= (coefficient)finalChange; + } + } + } + if (lastCG == 1) lastCG = 0; + } +} + /** RDOQ with CABAC * \returns void * Rate distortion optimized quantization for entropy @@ -455,7 +562,7 @@ void rdoq(encoder_state * const encoder_state, coefficient *coef, coefficient * int32_t qp_scaled = get_scaled_qp(type, encoder_state->global->QP, 0); uint32_t abs_sum = 0; - { + int32_t q_bits = QUANT_SHIFT + qp_scaled/6 + transform_shift; const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; @@ -515,10 +622,13 @@ void rdoq(encoder_state * const encoder_state, coefficient *coef, coefficient * memset( cost_coeff, 0, sizeof(double) * max_num_coeff ); memset( cost_sig, 0, sizeof(double) * max_num_coeff ); - memset( rate_inc_up, 0, sizeof(int32_t) * max_num_coeff ); - memset( rate_inc_down, 0, sizeof(int32_t) * max_num_coeff ); - memset( sig_rate_delta, 0, sizeof(int32_t) * max_num_coeff ); - memset( delta_u, 0, sizeof(int32_t) * max_num_coeff ); + + if (encoder->sign_hiding) { + memset(rate_inc_up, 0, sizeof(int32_t) * max_num_coeff); + memset(rate_inc_down, 0, sizeof(int32_t) * max_num_coeff); + memset(sig_rate_delta, 0, sizeof(int32_t) * max_num_coeff); + memset(delta_u, 0, sizeof(int32_t) * max_num_coeff); + } memset( cost_coeffgroup_sig, 0, sizeof(double) * 64 ); memset( sig_coeffgroup_flag, 0, sizeof(uint32_t) * 64 ); @@ -577,16 +687,22 @@ void rdoq(encoder_state * const encoder_state, coefficient *coef, coefficient * level = get_coded_level(encoder_state, &cost_coeff[ scanpos ], &cost_coeff0[ scanpos ], &cost_sig[ scanpos ], level_double, max_abs_level, ctx_sig, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, q_bits, temp, 0, type ); - sig_rate_delta[ blkpos ] = CTX_ENTROPY_BITS(&baseCtx[ctx_sig],1) - CTX_ENTROPY_BITS(&baseCtx[ctx_sig],0); + if (encoder->sign_hiding) { + sig_rate_delta[blkpos] = CTX_ENTROPY_BITS(&baseCtx[ctx_sig], 1) - CTX_ENTROPY_BITS(&baseCtx[ctx_sig], 0); + } } - delta_u[ blkpos ] = (level_double - ((int32_t)level << q_bits)) >> (q_bits-8); - if( level > 0 ) { - int32_t rate_now = get_ic_rate( encoder_state, level, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, type); - rate_inc_up [blkpos] = get_ic_rate( encoder_state, level+1, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, type) - rate_now; - rate_inc_down[blkpos] = get_ic_rate( encoder_state, level-1, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, type) - rate_now; - } else { // level == 0 - rate_inc_up[blkpos] = CTX_ENTROPY_BITS(&base_one_ctx[one_ctx],0); + + if (encoder->sign_hiding) { + delta_u[blkpos] = (level_double - ((int32_t)level << q_bits)) >> (q_bits - 8); + if (level > 0) { + int32_t rate_now = get_ic_rate(encoder_state, level, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, type); + rate_inc_up[blkpos] = get_ic_rate(encoder_state, level + 1, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, type) - rate_now; + rate_inc_down[blkpos] = get_ic_rate(encoder_state, level - 1, one_ctx, abs_ctx, go_rice_param, c1_idx, c2_idx, type) - rate_now; + } else { // level == 0 + rate_inc_up[blkpos] = CTX_ENTROPY_BITS(&base_one_ctx[one_ctx], 0); + } } + dest_coeff[blkpos] = (coefficient)level; base_cost += cost_coeff[scanpos]; @@ -759,100 +875,10 @@ void rdoq(encoder_state * const encoder_state, coefficient *coef, coefficient * for ( scanpos = best_last_idx_p1; scanpos <= last_scanpos; scanpos++ ) { dest_coeff[ scan[ scanpos ] ] = 0; } -#if ENABLE_SIGN_HIDING == 1 - if(abs_sum >= 2) { - int64_t rd_factor = (int64_t) ( - g_inv_quant_scales[qp_scaled%6] * g_inv_quant_scales[qp_scaled%6] * (1<<(2*(qp_scaled/6))) - / encoder_state->global->cur_lambda_cost / 16 / (1<<(2*(encoder->bitdepth-8))) - + 0.5); - int32_t lastCG = -1; - int32_t absSum = 0; - int32_t n,subset; - for (subset = (width*height-1) >> LOG2_SCAN_SET_SIZE; subset >= 0; subset--) { - int32_t subPos = subset << LOG2_SCAN_SET_SIZE; - int32_t firstNZPosInCG=SCAN_SET_SIZE, lastNZPosInCG = -1; - absSum = 0; - - for(n = SCAN_SET_SIZE-1; n >= 0; --n ) { - if( dest_coeff[ scan[ n + subPos ]] ) { - lastNZPosInCG = n; - break; - } - } - - for(n = 0; n =0 && lastCG==-1) lastCG = 1; - - if (lastNZPosInCG-firstNZPosInCG >= SBH_THRESHOLD ) { - int32_t signbit = (dest_coeff[scan[subPos+firstNZPosInCG]]>0?0:1); - if( signbit!=(absSum&0x1) ) { // hide but need tune - // calculate the cost - int64_t minCostInc = MAX_INT64, curCost=MAX_INT64; - int32_t minPos =-1, finalChange=0, curChange=0; - - for( n = (lastCG==1?lastNZPosInCG:SCAN_SET_SIZE-1) ; n >= 0; --n ) { - uint32_t blkpos = scan[ n + subPos ]; - if(dest_coeff[ blkpos ] != 0 ) { - int64_t costUp = rd_factor * (-delta_u[blkpos]) + rate_inc_up[blkpos]; - int64_t costDown = rd_factor * ( delta_u[blkpos]) + rate_inc_down[blkpos] - - ( abs(dest_coeff[blkpos])==1?((1<<15)+sig_rate_delta[blkpos]):0 ); - - if(lastCG==1 && lastNZPosInCG==n && abs(dest_coeff[blkpos])==1) { - costDown -= (4<<15); - } - - if(costUp= 0) ? 0 : 1) != signbit ) curCost = MAX_INT64; - } - } - - if( curCost=0) { - dest_coeff[minPos] += (coefficient)finalChange; - } else { - dest_coeff[minPos] -= (coefficient)finalChange; - } - } - } - if(lastCG==1) lastCG = 0; - } - } -#endif + if (encoder->sign_hiding && abs_sum >= 2) { + rdoq_sign_hiding(encoder_state, qp_scaled, scan, + delta_u, rate_inc_up, rate_inc_down, sig_rate_delta, + width, coef, dest_coeff); } }