📄 umc_h264_me_new.cpp
字号:
{
Ipp32s uMB = curr_slice->m_CurMBAddr;
bool bBSlice = BPREDSLICE == curr_slice->m_slice_type;
bool is_bwd_pred = (list_id == LIST_1);
Ipp32s i;
H264EncoderFrame<PixType> *pPrevFrm = GetRefPicList(curr_slice, list_id, curr_slice->m_is_cur_mb_field, uMB & 1)->m_RefPicList[0];
// set of candidates
Ipp32s mv_num = 1;
// predicted, calculated already
meInfo->candMV[0].mvx = (Ipp16s)(meInfo->predictedMV.mvx >> SUB_PEL_SHIFT);
meInfo->candMV[0].mvy = (Ipp16s)(meInfo->predictedMV.mvy >> SUB_PEL_SHIFT);
// zero vector
meInfo->candMV[1] = null_mv;
if (meInfo->candMV[1] != meInfo->candMV[0])
mv_num = 2;
// above MV
Ipp32s above_addr = curr_slice->m_cur_mb.CurrentMacroblockNeighbours.mb_B;
if (above_addr >= 0) {
const H264MotionVector &above = m_pCurrentFrame->m_mbinfo.MV[list_id][above_addr].MotionVectors[12];
meInfo->candMV[mv_num].mvx = above.mvx >> SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy = above.mvy >> SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
}
// left MV
Ipp32s left_addr = curr_slice->m_cur_mb.CurrentMacroblockNeighbours.mb_A;
if (left_addr >= 0) {
const H264MotionVector &left = m_pCurrentFrame->m_mbinfo.MV[list_id][left_addr].MotionVectors[3];
meInfo->candMV[mv_num].mvx = left.mvx >> SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy = left.mvy >> SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
}
// topleft MV
Ipp32s topleft_addr = curr_slice->m_cur_mb.CurrentMacroblockNeighbours.mb_D;
if (topleft_addr >= 0) {
const H264MotionVector &topleft = m_pCurrentFrame->m_mbinfo.MV[list_id][topleft_addr].MotionVectors[15];
meInfo->candMV[mv_num].mvx = topleft.mvx >> SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy = topleft.mvy >> SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
}
// topright MV
if (curr_slice->m_CurMB_Y > 0 && curr_slice->m_CurMB_X < m_WidthInMBs - 1) {
Ipp32s topright_addr = uMB - m_WidthInMBs + 1;
const H264MotionVector &topright = m_pCurrentFrame->m_mbinfo.MV[list_id][topright_addr].MotionVectors[12];
meInfo->candMV[mv_num].mvx = topright.mvx >> SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy = topright.mvy >> SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
}
// ref bottom
if (curr_slice->m_CurMB_Y < m_HeightInMBs - 1) {
Ipp32s bottom_addr = uMB + m_WidthInMBs;
const H264MotionVector &bottom = pPrevFrm->m_mbinfo.MV[list_id][bottom_addr].MotionVectors[0];
if (!bBSlice) {
meInfo->candMV[mv_num] = bottom;
} else {
// Forward vector, needs to be scaled, but direction is correct
const Ipp32s uFwdRatio = curr_slice->DistScaleFactorMV[0];
const Ipp32s TR_RND = (1 << (TR_SHIFT - 1));
meInfo->candMV[mv_num].mvx = (Ipp16s) ((uFwdRatio * bottom.mvx + TR_RND) >> TR_SHIFT);
meInfo->candMV[mv_num].mvy = (Ipp16s) ((uFwdRatio * bottom.mvy + TR_RND) >> TR_SHIFT);
if (is_bwd_pred) {
// Backward vector, needs both scaling and direction changed derived the backward MV from the reference MV: MVb = MVf-MV = -(1-r1)*MV
meInfo->candMV[mv_num].mvx = (Ipp16s)(meInfo->candMV[mv_num].mvx - bottom.mvx);
meInfo->candMV[mv_num].mvy = (Ipp16s)(meInfo->candMV[mv_num].mvy - bottom.mvy);
}
}
meInfo->candMV[mv_num].mvx = bottom.mvx >> SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy = bottom.mvy >> SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
}
// ref right
if (curr_slice->m_CurMB_X < m_WidthInMBs - 1) {
Ipp32s right_addr = uMB + 1;
const H264MotionVector &right = pPrevFrm->m_mbinfo.MV[list_id][right_addr].MotionVectors[0];
if (!bBSlice) {
meInfo->candMV[mv_num] = right;
} else {
// Forward vector, needs to be scaled, but direction is correct
const Ipp32s uFwdRatio = curr_slice->DistScaleFactorMV[0];
const Ipp32s TR_RND = (1 << (TR_SHIFT - 1));
meInfo->candMV[mv_num].mvx = (Ipp16s) ((uFwdRatio * right.mvx + TR_RND) >> TR_SHIFT);
meInfo->candMV[mv_num].mvy = (Ipp16s) ((uFwdRatio * right.mvy + TR_RND) >> TR_SHIFT);
if (is_bwd_pred) {
// Backward vector, needs both scaling and direction changed derived the backward MV from the reference MV: MVb = MVf-MV = -(1-r1)*MV
meInfo->candMV[mv_num].mvx = (Ipp16s)(meInfo->candMV[mv_num].mvx - right.mvx);
meInfo->candMV[mv_num].mvy = (Ipp16s)(meInfo->candMV[mv_num].mvy - right.mvy);
}
}
meInfo->candMV[mv_num].mvx = right.mvx >> SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy = right.mvy >> SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
}
// ref current
H264MotionVector fwd_mv = pPrevFrm->m_mbinfo.MV[list_id][uMB].MotionVectors[0];
if (!bBSlice) {
meInfo->candMV[mv_num] = fwd_mv;
} else {
// Forward vector, needs to be scaled, but direction is correct
const Ipp32s uFwdRatio = curr_slice->DistScaleFactorMV[0];
const Ipp32s TR_RND = (1 << (TR_SHIFT - 1));
meInfo->candMV[mv_num].mvx = (Ipp16s) ((uFwdRatio * fwd_mv.mvx + TR_RND) >> TR_SHIFT);
meInfo->candMV[mv_num].mvy = (Ipp16s) ((uFwdRatio * fwd_mv.mvy + TR_RND) >> TR_SHIFT);
if (is_bwd_pred) {
// Backward vector, needs both scaling and direction changed derived the backward MV from the reference MV: MVb = MVf-MV = -(1-r1)*MV
meInfo->candMV[mv_num].mvx = (Ipp16s)(meInfo->candMV[mv_num].mvx - fwd_mv.mvx);
meInfo->candMV[mv_num].mvy = (Ipp16s)(meInfo->candMV[mv_num].mvy - fwd_mv.mvy);
}
}
meInfo->candMV[mv_num].mvx >>= SUB_PEL_SHIFT;
meInfo->candMV[mv_num].mvy >>= SUB_PEL_SHIFT;
for (i = 0; i < mv_num; i++) {
if (meInfo->candMV[mv_num] == meInfo->candMV[i]) {
mv_num --;
break;
}
}
mv_num++;
meInfo->candNum = mv_num;
}
template <class PixType, class CoeffsType> bool H264CoreEncoder<PixType,CoeffsType>::CheckSkip(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice, H264MotionVector &cmpMV)
{
H264MotionVector skip_vec;
Skip_MV_Predicted(curr_slice, curr_slice->m_CurMBAddr, &skip_vec);
if ((abs(cmpMV.mvx - skip_vec.mvx) > 1) || (abs(cmpMV.mvy - skip_vec.mvy) > 1))
return false;
H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
H264EncoderFrame<PixType> **pRefPicList0 = GetRefPicList(curr_slice, LIST_0, curr_slice->m_is_cur_mb_field, curr_slice->m_CurMBAddr&1)->m_RefPicList;
Ipp8s *pFields0 = GetRefPicList(curr_slice, LIST_0, curr_slice->m_is_cur_mb_field, curr_slice->m_CurMBAddr&1)->m_Prediction;
PixType *const pInterpBuf = curr_slice->m_pMBEncodeBuffer;
Ipp16s* pDiffBuf = (Ipp16s*) (curr_slice->m_pMBEncodeBuffer + 512);
CoeffsType *pTransformResult = (CoeffsType*)(pDiffBuf + 16);
T_EncodeMBOffsets *pMBOffset = &m_pMBOffsets[curr_slice->m_CurMBAddr];
Ipp32s pitchPixels = m_pCurrentFrame->pitchPixels()<<curr_slice->m_is_cur_mb_field;
PixType* pSrcPlane = m_pCurrentFrame->m_pYPlane;
Ipp32u offset = m_pMBOffsets[curr_slice->m_CurMBAddr].uLumaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field];
Ipp32s iNumCoeffs, iLastCoeff, iXType, iYType;
PixType *pRef = pRefPicList0[0]->m_pYPlane + offset + curr_slice->m_InitialOffset[pFields0[0]];
pRef += SubpelMVAdjust(&skip_vec, pitchPixels, iXType, iYType);
#ifdef NEW_INTERPOLATE
Interpolate(pRef, pitchPixels, pInterpBuf, 16, iXType, iYType, size16x16, skip_vec.mvy, m_CurMB_Y*16);
#else
ippiInterpolateLuma_H264(pRef, pitchPixels*sizeof(PixType), pInterpBuf, 16*sizeof(PixType), iXType, iYType, size16x16, m_PicParamSet.bit_depth_luma);
#endif
Ipp32s coeffs_cost = 0;
Ipp32u uMBQP = getLumaQP(cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.bit_depth_luma);
Ipp32s chromaQP = getChromaQP(cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.chroma_qp_index_offset, m_SeqParamSet.bit_depth_chroma);
// code block
for (Ipp32s uBlock = 0; uBlock < 16; uBlock ++) {
PixType* pPredBuf = pInterpBuf + xoff[uBlock] + yoff[uBlock]*16;
Diff4x4(pPredBuf, pSrcPlane + offset, pitchPixels*sizeof(PixType), pDiffBuf);
ippiTransformQuantResidual_H264(pDiffBuf, pTransformResult,(Ipp32s)uMBQP,&iNumCoeffs,0, enc_single_scan[curr_slice->m_is_cur_mb_field], &iLastCoeff);
coeffs_cost += CalculateCoeffsCost(pTransformResult, 16, dec_single_scan[curr_slice->m_is_cur_mb_field]);
if (coeffs_cost >= 6) return false;
offset += m_EncBlockOffsetInc[curr_slice->m_is_cur_mb_field][uBlock];
}
if (m_PicParamSet.chroma_format_idc != 0) {
offset = pMBOffset->uChromaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field];
H264MotionVector chroma_skip_vec = skip_vec;
if( m_PicParamSet.chroma_format_idc == 1 ){
if (!curr_slice->m_is_cur_mb_bottom_field && pFields0[0]) chroma_skip_vec.mvy += - 2;
else if (curr_slice->m_is_cur_mb_bottom_field && !pFields0[0]) chroma_skip_vec.mvy += 2;
}
IppiSize chroma_size;
if( m_PicParamSet.chroma_format_idc == 1){ //420
chroma_size = size8x8;
}else if( m_PicParamSet.chroma_format_idc == 2){ //422
chroma_size = size8x16;
}
CoeffsType* pQBuf = (CoeffsType*) (pTransformResult + 16);
CoeffsType* pDCBuf = (CoeffsType*) (pQBuf + 16); // Used for both luma and chroma DC blocks
Ipp16s* pMassDiffBuf = (Ipp16s*) (pDCBuf + 16);
Ipp32s start_block = 16, last_block = 20;
if(m_PicParamSet.chroma_format_idc == 2) start_block = 16, last_block = 24;
pSrcPlane = m_pCurrentFrame->m_pUPlane;
pRef = pRefPicList0[0]->m_pUPlane + offset + curr_slice->m_InitialOffset[pFields0[0]];
Ipp32s mv_offset = SubpelChromaMVAdjust(&chroma_skip_vec, pitchPixels, iXType, iYType, m_PicParamSet.chroma_format_idc);
for (Ipp32s i = 0; i < 2 ; i++) {
pRef += mv_offset;
#ifdef NEW_INTERPOLATE
Interpolate_Cr(pRef, pitchPixels, pInterpBuf, 16, iXType, iYType, size16x16, chroma_skip_vec.mvy, m_CurMB_Y*16);
#else
ippiInterpolateChroma_H264(pRef, pitchPixels*sizeof(PixType), pInterpBuf, 16*sizeof(PixType), iXType, iYType, chroma_size, m_SeqParamSet.bit_depth_chroma);
#endif
ippiSumsDiff8x8Blocks4x4(pSrcPlane + offset, pitchPixels, pInterpBuf, 16, pDCBuf, pMassDiffBuf);
if( m_PicParamSet.chroma_format_idc == 2 ){
// Process second part of 2x4 block for DC coeffs
ippiSumsDiff8x8Blocks4x4(pSrcPlane + offset+8*pitchPixels, // source pels
pitchPixels, // source pitch
pInterpBuf+8*16, // predictor pels
16,
pDCBuf+4, // result buffer
pMassDiffBuf+64); //+Offset for second path
}
// 2x2 forward transform
switch( m_PicParamSet.chroma_format_idc ){
case 1:
ippiTransformQuantChromaDC_H264(pDCBuf, pQBuf, chromaQP,&iNumCoeffs,(curr_slice->m_slice_type == INTRASLICE),1);
break;
case 2:
ippiTransformQuantChroma422DC_H264(pDCBuf, pQBuf,chromaQP,&iNumCoeffs,(curr_slice->m_slice_type == INTRASLICE),1);
break;
}
if (pDCBuf[0] || pDCBuf[1] || pDCBuf[2] || pDCBuf[3]) return false;
if( m_PicParamSet.chroma_format_idc == 2 && (pDCBuf[4] || pDCBuf[5] || pDCBuf[6] || pDCBuf[7]) ) return false;
coeffs_cost = 0;
for (Ipp32s uBlock = start_block; uBlock < last_block; uBlock ++) {
Ipp16s* pTempDiffBuf = pMassDiffBuf+(uBlock - start_block)*16;
ippiTransformQuantResidual_H264(pTempDiffBuf, pTransformResult, chromaQP, &iNumCoeffs, 0, enc_single_scan[curr_slice->m_is_cur_mb_field], &iLastCoeff);
coeffs_cost += CalculateCoeffsCost(pTransformResult, 15, &dec_single_scan[curr_slice->m_is_cur_mb_field][1]);
if (coeffs_cost >= 7) return false;
offset += m_EncBlockOffsetInc[curr_slice->m_is_cur_mb_field][uBlock];
}
if( m_PicParamSet.chroma_format_idc == 1 ){
start_block = 20;
last_block = 24;
}else if( m_PicParamSet.chroma_format_idc == 2 ){
start_block = 24;
last_block = 32;
}
pSrcPlane = m_pCurrentFrame->m_pVPlane;
offset = pMBOffset->uChromaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field];
pRef = pRefPicList0[0]->m_pVPlane + offset + curr_slice->m_InitialOffset[pFields0[0]];
}
}
for (Ipp32s i = 0; i < 16; i ++) {
cur_mb.MVs[LIST_0]->MotionVectors[i] = skip_vec;
cur_mb.MVs[LIST_1]->MotionVectors[i] = null_mv;
cur_mb.RefIdxs[LIST_0]->RefIdxs[i] = (T_RefIdx)0;
cur_mb.RefIdxs[LIST_1]->RefIdxs[i] = (T_RefIdx)-1;
}
curr_slice->m_cur_mb.LocalMacroblockInfo->cbp_luma = 0x000000;
curr_slice->m_cur_mb.LocalMacroblockInfo->cbp_chroma = 0;//0xffffffff;
curr_slice->m_cur_mb.LocalMacroblockInfo->cbp = 0;
curr_slice->m_cur_mb.GlobalMacroblockInfo->mbtype = MBTYPE_SKIPPED;
// cur_mb.GlobalMacroblockInfo->sbtype[0] = MBTYPE_SKIPPED;
return true;
}
template <class PixType, class CoeffsType> bool H264CoreEncoder<PixType,CoeffsType>::CheckSkipB(H264EncoderThreadPrivateSlice<PixType,CoeffsType>* curr_slice)
{
PixType* pInterpBuf = curr_slice->m_pPred4DirectB;
Ipp16s* pDiffBuf = (Ipp16s*) (curr_slice->m_pMBEncodeBuffer + 5
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -