📄 umc_h264_aic.cpp
字号:
// of sizeof(PixSize)*16.
//
////////////////////////////////////////////////////////////////////////////////
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::GetPredBlock(Ipp32u uMode, PixType *pPredBuf, PixType *PredPel)
{
Ipp32u sum;
Ipp32s i, j;
PixType PredVal;
// for the specified mode create the prediction block from the predictor
// pels
switch (uMode)
{
case 0:
// mode 0: vertical prediction (from above)
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++) {
pPredBuf[i] = PredPel[i+1]; // ABCD
}
pPredBuf += 16;
}
break;
case 1:
// mode 1: horizontal prediction (from left)
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++) {
pPredBuf[i] = PredPel[j+9]; // IJKL
}
pPredBuf += 16;
}
break;
case 2:
// mode 2: DC prediction
sum = 0;
for (i = 0; i < 4; i++) {
sum += PredPel[i+9]; // IJKL
sum += PredPel[i+1]; // ABCD
}
PredVal = (PixType)((sum + 4) / 8);
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++) {
// Warning: The WinCE compiler generated incorrect code (storing
// predictor in the first byte only) when the following line of
// code was:
// pPredBuf[i] = (PixType)sum;
pPredBuf[i] = PredVal;
}
pPredBuf += 16;
}
break;
case 3:
// mode 3: diagonal down/left prediction
P_a = (P_A + ((P_B) << 1) + P_C + 2) >> 2;
P_b = P_e = (P_B + ((P_C) << 1) + P_D + 2) >> 2;
P_c = P_f = P_i = (P_C + ((P_D) << 1) + P_E + 2) >> 2;
P_d = P_g = P_j = P_m = (P_D + ((P_E) << 1) + P_F + 2) >> 2;
P_h = P_k = P_n = (P_E + ((P_F) << 1) + P_G + 2) >> 2;
P_l = P_o = (P_F + ((P_G) << 1) + P_H + 2) >> 2;
P_p = (P_G + ((P_H) << 1) + P_H + 2) >> 2;
break;
case 4:
// mode 4: diagonal down/right prediction
P_m = (P_J + ((P_K) << 1) + P_L + 2) >> 2;
P_i = P_n = (P_I + ((P_J) << 1) + P_K + 2) >> 2;
P_e = P_j = P_o = (P_Z + ((P_I) << 1) + P_J + 2) >> 2;
P_a = P_f = P_k = P_p = (P_A + ((P_Z) << 1) + P_I + 2) >> 2;
P_b = P_g = P_l = (P_Z + ((P_A) << 1) + P_B + 2) >> 2;
P_c = P_h = (P_A + ((P_B) << 1) + P_C + 2) >> 2;
P_d = (P_B + ((P_C) << 1) + P_D + 2) >> 2;
break;
case 5 :
// mode 5: vertical-right prediction
P_a = P_j = (P_Z + P_A + 1) >> 1;
P_b = P_k = (P_A + P_B + 1) >> 1;
P_c = P_l = (P_B + P_C + 1) >> 1;
P_d = (P_C + P_D + 1) >> 1;
P_e = P_n = (P_I + ((P_Z) << 1) + P_A + 2) >> 2;
P_f = P_o = (P_Z + ((P_A) << 1) + P_B + 2) >> 2;
P_g = P_p = (P_A + ((P_B) << 1) + P_C + 2) >> 2;
P_h = (P_B + ((P_C) << 1) + P_D + 2) >> 2;
P_i = (P_Z + ((P_I) << 1) + P_J + 2) >> 2;
P_m = (P_I + ((P_J) << 1) + P_K + 2) >> 2;
break;
case 6 :
// mode 6: horizontal-down prediction
P_a = P_g = (P_Z + P_I + 1) >> 1;
P_b = P_h = (P_I + ((P_Z) << 1) + P_A + 2) >> 2;
P_c = (P_Z + ((P_A) << 1) + P_B + 2) >> 2;
P_d = (P_A + ((P_B) << 1) + P_C + 2) >> 2;
P_e = P_k = (P_I + P_J + 1) >> 1;
P_f = P_l = (P_Z + ((P_I) << 1) + P_J + 2) >> 2;
P_i = P_o = (P_J + P_K + 1) >> 1;
P_j = P_p = (P_I + ((P_J) << 1) + P_K + 2) >> 2;
P_m = (P_K + P_L + 1) >> 1;
P_n = (P_J + ((P_K) << 1) + P_L + 2) >> 2;
break;
case 7 :
// mode 7: vertical-left prediction
P_a = (P_A + P_B + 1) >> 1;
P_b = P_i = (P_B + P_C + 1) >> 1;
P_c = P_j = (P_C + P_D + 1) >> 1;
P_d = P_k = (P_D + P_E + 1) >> 1;
P_l = (P_E + P_F + 1) >> 1;
P_e = (P_A + ((P_B) << 1) + P_C + 2) >> 2;
P_f = P_m = (P_B + ((P_C) << 1) + P_D + 2) >> 2;
P_g = P_n = (P_C + ((P_D) << 1) + P_E + 2) >> 2;
P_h = P_o = (P_D + ((P_E) << 1) + P_F + 2) >> 2;
P_p = (P_E + ((P_F) << 1) + P_G + 2) >> 2;
break;
case 8 :
// mode 8: horizontal-up prediction
P_a = (P_I + P_J + 1) >> 1;
P_b = (P_I + ((P_J) << 1) + P_K + 2) >> 2;
P_c = P_e = (P_J + P_K + 1) >> 1;
P_d = P_f = (P_J + ((P_K) << 1) + P_L + 2) >> 2;
P_g = P_i = (P_K + P_L + 1) >> 1;
P_h = P_j = (P_K + ((P_L) << 1) + P_L + 2) >> 2;
P_k = P_l = P_m = P_n = P_o = P_p = (P_L);
break;
default:
break;
} // switch
} // GetPredBlock
////////////////////////////////////////////////////////////////////////////////
//
// AIModeSelectOneBlock
//
// Choose the best advanced intra mode for coding one block, store at
// *pMode. Also return the RD-adjusted SAD for the chosen mode. Also
// save predictor pels in provided buffer when the buffer pointer is
// not NULL.
//
// Used both in ME phase, for INTRA/INTER decision using original source
// pels for predictors, and later in block encoding using reconstructed
// pels for predictors.
//
//
// In the ME phase (signaled by pPred==NULL) only modes 0,1,2 are checked
// in the interest of CPU performance. The resulting best SAD is good enough
// for MB mode selection.
//
////////////////////////////////////////////////////////////////////////////////
template <class PixType, class CoeffsType>
Ipp32u H264CoreEncoder<PixType,CoeffsType>::AIModeSelectOneBlock(
H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice,
PixType* pSrcBlock, // pointer to upper left pel of source block
PixType* pReconBlock, // pointer to same block in reconstructed picture
Ipp32u uBlock, // which 4x4 of the MB (0..15)
T_AIMode* intra_types, // selected mode goes here
PixType* pPred) // predictor pels for selected mode goes here
// if not NULL
{
Ipp32u uMinSAD;
T_AIMode Mode, ModeAbove, ModeLeft, ProbMode;
__ALIGN16 PixType uPred[16*NUM_AI_MODES*4]; // predictor pels, all modes, each 4 rows, pitch=16
PixType PredPel[13];
T_AIMode *pMode = &intra_types[uBlock];
// get AI mode of block above and block to left to use to add bit cost
// of signaling each mode for this block to SAD. Take care not to go
// beyond the AIMode array, at top and left picture edges.
ModeLeft = -1;
#ifdef NOINTRALEFTDEP
// If this block is on the left MB edge, assume we don't know anything about the block to the left.
if (BLOCK_IS_ON_LEFT_EDGE(block_subblock_mapping[uBlock]))
{
if (curr_slice->m_cur_mb.CurrentBlockNeighbours.mbs_left[block_subblock_mapping[uBlock] / 4].mb_num >= 0)
ModeLeft = 2;
} else {
Ipp32s block_num = block_subblock_mapping[uBlock] - 1; // neighbour in non-raster order
block_num = block_subblock_mapping[block_num];
ModeLeft = intra_types[block_num];
}
#else
if (BLOCK_IS_ON_LEFT_EDGE(block_subblock_mapping[uBlock]))
{
H264BlockLocation block = curr_slice->m_cur_mb.CurrentBlockNeighbours.mbs_left[block_subblock_mapping[uBlock] >> 2];
if (block.mb_num >= 0)
{
ModeLeft = m_mbinfo.intra_types[block.mb_num].intra_types[block_subblock_mapping[block.block_num]];
}
} else {
Ipp32s block_num = block_subblock_mapping[uBlock] - 1; // neighbour in non-raster order
block_num = block_subblock_mapping[block_num];
ModeLeft = intra_types[block_num];
}
#endif // NOINTRALEFTDEP
ModeAbove = -1;
if (BLOCK_IS_ON_TOP_EDGE(block_subblock_mapping[uBlock]))
{
H264BlockLocation block = curr_slice->m_cur_mb.CurrentBlockNeighbours.mb_above;
if (block.mb_num >= 0)
{
block.block_num += block_subblock_mapping[uBlock];
ModeAbove = m_mbinfo.intra_types[block.mb_num].intra_types[block_subblock_mapping[block.block_num]];
}
}else {
Ipp32s block_num = block_subblock_mapping[uBlock] - 4; // neighbour in non-raster order
block_num = block_subblock_mapping[block_num];
ModeAbove = intra_types[block_num];
}
Ipp32s pitchPixels = m_pCurrentFrame->pitchPixels()<<curr_slice->m_is_cur_mb_field;
PixType* pLeftRefBlock;
Ipp32u uLeftPitch;
PixType* pAboveRefBlock;
Ipp32u uAbovePitch;
PixType* pAboveLeftRefBlock;
Ipp32u uAboveLeftPitch;
if (curr_slice->m_use_transform_for_intra_decision){
uLeftPitch = uAbovePitch = uAboveLeftPitch = 16;
#ifdef H264_RD_OPT
pLeftRefBlock = pAboveRefBlock = pAboveLeftRefBlock = curr_slice->m_cur_mb.mb4x4.reconstruct + xoff[uBlock] + yoff[uBlock]*16;
#else
pLeftRefBlock = pAboveRefBlock = pAboveLeftRefBlock = pPred + 256;
#endif
if (ModeAbove == -1 || BLOCK_IS_ON_TOP_EDGE(block_subblock_mapping[uBlock])){
pAboveRefBlock = pReconBlock;
uAbovePitch = pitchPixels;
pAboveLeftRefBlock = pReconBlock;
uAboveLeftPitch = pitchPixels;
}
if (BLOCK_IS_ON_LEFT_EDGE(block_subblock_mapping[uBlock])){
pLeftRefBlock = pReconBlock;
uLeftPitch = pitchPixels;
pAboveLeftRefBlock = pReconBlock;
uAboveLeftPitch = pitchPixels;
}
} else {
pLeftRefBlock = pReconBlock;
uLeftPitch = pitchPixels;
pAboveRefBlock = pReconBlock;
uAbovePitch = pitchPixels;
pAboveLeftRefBlock = pReconBlock;
uAboveLeftPitch = pitchPixels;
}
// Get the above and left predictor pels to PredPel
GetBlockPredPels(curr_slice, pLeftRefBlock, uLeftPitch, pAboveRefBlock, uAbovePitch, pAboveLeftRefBlock, uAboveLeftPitch, uBlock, PredPel);
// If all the predictor pels are equal, all modes will give the same results.
Ipp32s iQP = getLumaQP51(curr_slice->m_cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.bit_depth_luma);
ProbMode = MIN(ModeAbove, ModeLeft);
if (ProbMode == -1) ProbMode = 2;
GetPredBlock(2, &uPred[2*64], PredPel);
if (m_Analyse & ANALYSE_SAD)
uMinSAD = BITS_COST((ProbMode == 2)? 1:4, glob_RDQM[iQP]) + SAD4x4(pSrcBlock, pitchPixels*sizeof(PixType), &uPred[2*64], 16*sizeof(PixType));
else
uMinSAD = BITS_COST((ProbMode == 2)? 1:4, glob_RDQM[iQP]) + SATD4x4(pSrcBlock, pitchPixels*sizeof(PixType), &uPred[2*64], 16*sizeof(PixType));
*pMode = 2;
Ipp32s* modes;
Ipp32s nmodes=0;
if( ( ModeAbove >= 0 ) && ( ModeLeft >= 0 ) ){
if (!uBlock && (curr_slice->m_cur_mb.CurrentBlockNeighbours.mb_above_left.mb_num < 0)){
modes = &intra_modes[0][0];
nmodes=5;
}else{
modes = &intra_modes[1][0];
nmodes=8;
}
}else if( ModeAbove >= 0){
modes = &intra_modes[2][0];
nmodes=3;
}else if( ModeLeft >= 0 ){
modes = &intra_modes[3][0];
nmodes=2;
}
if( nmodes ){
Ipp32u ModeSAD[9];
Ipp32s i;
if (m_Analyse & ANALYSE_SAD){
for (i=0; i < nmodes; i++){
Mode = modes[i];
GetPredBlock(Mode, &uPred[Mode*64], PredPel);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -