📄 quantize.c
字号:
pbi->FrameQIndex --; } // Re-initialise the q tables for forward and reverse transforms. init_quantizer ( cpi, qscale, (UINT8) pbi->FrameQIndex ); init_dequantizer ( pbi, qscale, (UINT8) pbi->FrameQIndex );}/***************************************************************************** * Routine: init_quantizer** Purpose: Used to initialize the encoding/decoding data structures* and to select DCT algorithm ** Parameters :* Input :* UINT32 scale_factor* Defines the factor by which to scale QUANT_ARRAY to* produce quantization_array** UINT8 QIndex :: * Index into Q table for current quantiser value.* Return value :* None.******************************************************************************/#define SHIFT16 (1<<16)void init_quantizer ( CP_INSTANCE *cpi, UINT32 scale_factor, UINT8 QIndex ){ int i; // Loop counters double ZBinFactor; double RoundingFactor; double temp_fp_quant_coeffs; double temp_fp_quant_round; double temp_fp_ZeroBinSize; PB_INSTANCE *pbi = &cpi->pb; // Pointers to encoder/decoder specific tables Q_LIST_ENTRY * Inter_coeffs; Q_LIST_ENTRY * Y_coeffs; Q_LIST_ENTRY * UV_coeffs; Q_LIST_ENTRY * DcScaleFactorTable; Q_LIST_ENTRY * UVDcScaleFactorTable; // Notes on setup of quantisers. // The initial multiplication by the scale factor is done in the INT32 domain // to insure that the precision in the quantiser is the same as in the inverse // quantiser where all calculations are integer. // The "<< 2" is a normalisation factor for the forward DCT transform. // New version rounding and ZB characteristics. Inter_coeffs = Inter_coeffsV1; Y_coeffs = Y_coeffsV1; UV_coeffs = UV_coeffsV1; DcScaleFactorTable = DcScaleFactorTableV1; UVDcScaleFactorTable = DcScaleFactorTableV1; ZBinFactor = 0.9; switch(cpi->Sharpness) { case 0: ZBinFactor = 0.65; if ( scale_factor <= 50 ) RoundingFactor = 0.499; else RoundingFactor = 0.46; break; case 1: ZBinFactor = 0.75; if ( scale_factor <= 50 ) RoundingFactor = 0.476; else RoundingFactor = 0.400; break; default: ZBinFactor = 0.9; if ( scale_factor <= 50 ) RoundingFactor = 0.476; else RoundingFactor = 0.333; break; } // Use fixed multiplier for intra Y DC temp_fp_quant_coeffs = (double)(((UINT32)(DcScaleFactorTable[QIndex] * Y_coeffs[0])/100) << 2); if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 2 ) temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 2; temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_Y_round[0] = (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_Y[0] = (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_Y_coeffs[0] = (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); // Intra UV temp_fp_quant_coeffs = (double)(((UINT32)(UVDcScaleFactorTable[QIndex] * UV_coeffs[0])/100) << 2); if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 2) temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 2; temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_UV_round[0] = (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_UV[0] = (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_UV_coeffs[0]= (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); // Inter Y temp_fp_quant_coeffs = (double)(((UINT32)(DcScaleFactorTable[QIndex] * Inter_coeffs[0])/100) << 2); if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 4) temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 4; temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_Inter_round[0]= (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_Inter[0]= (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_Inter_coeffs[0]= (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); // Inter UV temp_fp_quant_coeffs = (double)(((UINT32)(UVDcScaleFactorTable[QIndex] * Inter_coeffs[0])/100) << 2); if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 4) temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 4; temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_InterUV_round[0]= (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_InterUV[0]= (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_InterUV_coeffs[0]= (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); for ( i = 1; i < 64; i++ ) { // now scale coefficients by required compression factor // Intra Y temp_fp_quant_coeffs = (double)(((UINT32)(scale_factor * Y_coeffs[i]) / 100 ) << 2 ); if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY) ) temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY); temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_Y_round[i] = (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_Y[i] = (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_Y_coeffs[i] = (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); // Intra UV temp_fp_quant_coeffs = (double)(((UINT32)(scale_factor * UV_coeffs[i]) / 100 ) << 2 ); if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY)) temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY); temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_UV_round[i] = (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_UV[i] = (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_UV_coeffs[i] = (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); // Inter Y temp_fp_quant_coeffs = (double)(((UINT32)(scale_factor * Inter_coeffs[i]) / 100 ) << 2 ); if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY * 2) ) temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY * 2); temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_Inter_round[i] = (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_Inter[i] = (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_Inter_coeffs[i] = (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); // Inter UV temp_fp_quant_coeffs = (double)(((UINT32)(scale_factor * Inter_coeffs[i]) / 100 ) << 2 ); if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY * 2) ) temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY * 2); temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; pbi->fp_quant_InterUV_round[i] = (INT32) (0.5 + temp_fp_quant_round); temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; pbi->fp_ZeroBinSize_InterUV[i] = (INT32) (0.5 + temp_fp_ZeroBinSize); temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; pbi->fp_quant_InterUV_coeffs[i] = (INT32) (0.5 + SHIFT16 * temp_fp_quant_coeffs); } pbi->fquant_coeffs = pbi->fp_quant_Y_coeffs;}/****************************************************************************//* *//* Select Quantisation Parameters *//* *//* void select_Y_quantiser ( void ) *//* sets quantiser to use for Intra Y *//* void select_Inter_quantiser ( void ) *//* sets quantiser to use for Inter Y *//* void select_UV_quantiser ( void ) *//* sets quantiser to use UV compression constants *//* *//* void select_InterUV_quantiser ( void ) *//* sets quantiser to use for Inter UV *//****************************************************************************/void select_Y_quantiser ( PB_INSTANCE *pbi ){ pbi->fquant_coeffs = pbi->fp_quant_Y_coeffs; pbi->fquant_round = pbi->fp_quant_Y_round; pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Y;}void select_Inter_quantiser ( PB_INSTANCE *pbi ){ pbi->fquant_coeffs = pbi->fp_quant_Inter_coeffs; pbi->fquant_round = pbi->fp_quant_Inter_round; pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Inter;}void select_UV_quantiser ( PB_INSTANCE *pbi ){ pbi->fquant_coeffs = pbi->fp_quant_UV_coeffs; pbi->fquant_round = pbi->fp_quant_UV_round; pbi->fquant_ZbSize = pbi->fp_quant_UV_round;}void select_InterUV_quantiser ( PB_INSTANCE *pbi ){ pbi->fquant_coeffs = pbi->fp_quant_InterUV_coeffs; pbi->fquant_round = pbi->fp_quant_InterUV_round; pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_InterUV;}/**************************************************************************** * Routine: quantize** Purpose: Quantizes a block of pixels by dividing * each element by the corresponding entry in the quantization* array. Output is in a list of values in the zig-zag order.** Parameters :* Input :* DCT_block -- The block to by quantized* Output :* quantized_list -- The quantized values in zig-zag order** Return value :* None.** Persistent data referenced :* quantization_array Module static array read* zig_zag_index Module static array read* *****************************************************************************/#define MIN16 ((1<<16)-1)void quantize( PB_INSTANCE *pbi, INT16 * DCT_block, Q_LIST_ENTRY * quantized_list){ UINT32 i; /* Row index */ Q_LIST_ENTRY val; /* Quantised value. */ INT32 * FquantRoundPtr = pbi->fquant_round; INT32 * FquantCoeffsPtr = pbi->fquant_coeffs; INT32 * FquantZBinSizePtr = pbi->fquant_ZbSize; INT16 * DCT_blockPtr = DCT_block; UINT32 * QIndexPtr = (UINT32 *)pbi->quant_index; INT32 temp; // Set the quantized_list to default to 0 memset( quantized_list, 0, 64 * sizeof(Q_LIST_ENTRY) ); // Note that we add half divisor to effect rounding on positive number for( i = 0; i < pbi->Configuration.VFragPixels; i++) { // Column 0 if ( DCT_blockPtr[0] >= FquantZBinSizePtr[0] ) { temp = FquantCoeffsPtr[0] * ( DCT_blockPtr[0] + FquantRoundPtr[0] ) ; val = (Q_LIST_ENTRY) (temp>>16); quantized_list[QIndexPtr[0]] = ( val > 511 ) ? 511 : val; } else if ( DCT_blockPtr[0] <= -FquantZBinSizePtr[0] ) { temp = FquantCoeffsPtr[0] * ( DCT_blockPtr[0] - FquantRoundPtr[0] ) + MIN16; val = (Q_LIST_ENTRY) (temp>>16); quantized_list[QIndexPtr[0]] = ( val < -511 ) ? -511 : val; } // Column 1 if ( DCT_blockPtr[1] >= FquantZBinSizePtr[1] ) { temp = FquantCoeffsPtr[1] * ( DCT_blockPtr[1] + FquantRoundPtr[1] ) ; val = (Q_LIST_ENTRY) (temp>>16); quantized_list[QIndexPtr[1]] = ( val > 511 ) ? 511 : val; } else if ( DCT_blockPtr[1] <= -FquantZBinSizePtr[1] ) { temp = FquantCoeffsPtr[1] * ( DCT_blockPtr[1] - FquantRoundPtr[1] ) + MIN16; val = (Q_LIST_ENTRY) (temp>>16); quantized_list[QIndexPtr[1]] = ( val < -511 ) ? -511 : val; } // Column 2 if ( DCT_blockPtr[2] >= FquantZBinSizePtr[2] ) { temp = FquantCoeffsPtr[2] * ( DCT_blockPtr[2] + FquantRoundPtr[2] ) ; val = (Q_LIST_ENTRY) (temp>>16); quantized_list[QIndexPtr[2]] = ( val > 511 ) ? 511 : val; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -