📄 umc_h264_me.cpp
字号:
bestRefIdxs[SB_8x16_R] = ref_idx; PredictedMV[SB_8x16_R] = tempPredictedMV[SB_8x16_R]; } tempSAD = MVConstraint(xFactor - PredictedMV[SB_16x8_T].iMVx, yFactor - PredictedMV[SB_16x8_T].iMVy, pRDQM) + ref_constraint; tempSAD += ((Ipp32u)ThisSAD[0]+(Ipp32u)ThisSAD[1]); if (tempSAD < BestSADs[SB_16x8_T]) { BestSADs[SB_16x8_T] = tempSAD; BestMVs[SB_16x8_T].iMVx = (Ipp8s)xvec*SubPelFactor; BestMVs[SB_16x8_T].iMVy = (Ipp8s)yvec*SubPelFactor; bestRefIdxs[SB_16x8_T] = ref_idx; PredictedMV[SB_16x8_T] = tempPredictedMV[SB_16x8_T]; } tempSAD = MVConstraint(xFactor - PredictedMV[SB_16x8_B].iMVx, yFactor - PredictedMV[SB_16x8_B].iMVy, pRDQM) + ref_constraint; tempSAD += ((Ipp32u)ThisSAD[2]+(Ipp32u)ThisSAD[3]); if (tempSAD < BestSADs[SB_16x8_B]) { BestSADs[SB_16x8_B] = tempSAD; BestMVs[SB_16x8_B].iMVx = (Ipp8s)xvec*SubPelFactor; BestMVs[SB_16x8_B].iMVy = (Ipp8s)yvec*SubPelFactor; bestRefIdxs[SB_16x8_B] = ref_idx; PredictedMV[SB_16x8_B] = tempPredictedMV[SB_16x8_B]; } tempSAD = MVConstraint(xFactor - PredictedMV[SB_16x16].iMVx, yFactor - PredictedMV[SB_16x16].iMVy, pRDQM) + ref_constraint; tempSAD += ((Ipp32u)ThisSAD[0]+(Ipp32u)ThisSAD[1]+(Ipp32u)ThisSAD[2]+(Ipp32u)ThisSAD[3]); if (tempSAD < BestSADs[SB_16x16]) { BestSADs[SB_16x16] = tempSAD; BestMVs[SB_16x16].iMVx = (Ipp8s)xvec*SubPelFactor; BestMVs[SB_16x16].iMVy = (Ipp8s)yvec*SubPelFactor; bestRefIdxs[SB_16x16] = ref_idx; PredictedMV[SB_16x16] = tempPredictedMV[SB_16x16]; } } // for xvec } // for yvec } } // See if the result of the Best Initial MV is better if (uBestSAD16x16e < (Ipp32s) BestSADs[SB_16x16]) { BestSADs[SB_16x16] = uBestSAD16x16e; BestMVs[SB_16x16].iMVx = BestMV16x16.iMVx * SubPelFactor; BestMVs[SB_16x16].iMVy = BestMV16x16.iMVy * SubPelFactor; bestRefIdxs[SB_16x16] = ref_idx; } return;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void H264VideoEncoder::CMESplitOneMB_P_Slice( Ipp32u uMB, Ipp32u *puMBSAD, // return best total MB SAD here T_RefIdx bestRefIdxs[41], T_ECORE_MV BestMVs[41], Ipp32u BestSADs[41], T_ECORE_MV PredictedMV[41]){ const H264EncoderFrame *pRefFrame = 0; Ipp32u BestSAD, uRefFrame; Ipp8u BestMode; Ipp32s block, offset, pixel_offset; T_ECORE_MV tmpMV; T_ECORE_BIGMV tmpMVDelta; Ipp32u tempSAD = 0; const Ipp32s ME_MAX_SAD = INT_MAX >> 5; // Scaled down to allow sums of MAX without overflow. Ipp32u Best16x16 = ME_MAX_SAD; Ipp32u Best16x8 = ME_MAX_SAD; Ipp32u Best8x16 = ME_MAX_SAD; Ipp32u Best8x8 = ME_MAX_SAD; T_EncodeMBOffsets *pMBOffset = &m_pCurrentFrame->pMBOffsets[uMB]; Ipp32s uMVOffset = pMBOffset->uFirstBlockIndex; T_ECORE_MV *pMV = &m_pCurrentFrame->pMVL0[uMVOffset]; T_RefIdx *pRefIdxL0 = &m_pCurrentFrame->pRefIdxL0[uMVOffset]; H264EncoderFrame **pRefPicList0 = m_pCurrentFrame->GetRefPicList(0, LIST_0)->m_RefPicList; Ipp32s uPitch = m_pCurrentFrame->uPitch; uRefFrame = (m_pCurrentFrame->pMBData[uMB].uMBType == MBTYPE_BACKWARD) ? 1 : 0; // 16-byte aligned 256 byte (16x16) work buffer Ipp8u *pSPBuffer; pSPBuffer = m_pCurrentFrame->pMBEncodeBuffer + 256; Ipp32s uQP = m_pCurrentFrame->pMBData[uMB].uMBQP; Ipp16s *pRDQM = RDQM[uQP]; m_pCurrentFrame->pMBData[uMB].uCBP4x4 = 0xffffff; ////////////////////////////////////////////////////////////// // This code tries to find the best way to split the block // For Motion Estimation purposes // Start with 1 16x16 Block Best16x16 = BestSADs[SB_16x16]; // MV Constraint already added BestSAD = Best16x16; BestMode = 0; // If there is no Motion Estimation taking place, just select the // 16x16 and setup for exit if (m_info.me_search_x == 0 && m_info.me_search_y == 0) { unsigned int y, x; for (y = 0; y < 4*uWidthIn4x4Blocks; y+=uWidthIn4x4Blocks) { for (x = 0; x < 4; x++) { *(pMV + x + y) = BestMVs[SB_16x16]; *(pRefIdxL0 + x + y) = bestRefIdxs[SB_16x16]; } } m_pCurrentFrame->pMBData[uMB].uMBType = MBTYPE_INTER; *puMBSAD = BestSAD; return; } // Compare to 2 16x8 Blocks // Copy MV into place for next block predictor calc Best16x8 = BestSADs[SB_16x8_T] + BestSADs[SB_16x8_B] // MV Constraints already added + pRDQM[2]; // Two extra Bits for 16x8 in a P slice if (Best16x8 < BestSAD) { BestSAD = Best16x8; BestMode = 1; } // Compare to 2 8x16 Blocks Best8x16 = BestSADs[SB_8x16_L] + // MV Constraints already added BestSADs[SB_8x16_R] + pRDQM[2]; // Two extra Bits for 8x16 in a P slice if (Best8x16 < BestSAD) { BestSAD = Best8x16; BestMode = 2; } // For each 8x8 block, figure out the "best" way to code it. Ipp32u Block8x8Best[4] = {ME_MAX_SAD, ME_MAX_SAD, ME_MAX_SAD, ME_MAX_SAD}; Ipp32u Block8x8BestMode[4] = {MODE_8x8, MODE_8x8, MODE_8x8, MODE_8x8}; for (block = 0; block < 4; block++) { // First try 1 - 8x8 block if (block) { Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4], uRefFrame, &BestMVs[SB_8x8_TL+block], 2, 2, &tmpMV, &tmpMVDelta); Block8x8Best[block] = BestSADs[SB_8x8_TL+block] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); } else { Block8x8Best[block] = BestSADs[SB_8x8_TL]; // MV Constraint already added } Block8x8Best[block] += pRDQM[1]; // 1 extra bit for 8x8 if (m_info.me_split_8x8s) // Only do this if we are splitting 8x8 blocks { // Next, 2 - 8x4 blocks // Calc top predictor if (block) { Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4], uRefFrame, &BestMVs[SB_8x4_TL+block*2], 2, 1, &tmpMV, &tmpMVDelta); tempSAD = BestSADs[SB_8x4_TL+block*2] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); } else { tempSAD = BestSADs[SB_8x4_TL]; // MV Constraint already added // Fill in MV for use in Predictor calc for next subblock pMV[0] = BestMVs[SB_8x4_TL]; } // Calc bottom predictor Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4+2], uRefFrame, &BestMVs[SB_8x4_TL+1+block*2], 2, 1, &tmpMV, &tmpMVDelta); tempSAD += BestSADs[SB_8x4_TL+1+block*2] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); tempSAD += pRDQM[3]; // 3 extra bits for 8x4 if (tempSAD < Block8x8Best[block]) { Block8x8Best[block] = tempSAD; Block8x8BestMode[block] = MODE_8x4; } // Next, 2 - 4x8 blocks // Calc left predictor if (block) { Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4], uRefFrame, &BestMVs[SB_4x8_TL+block*2], 1, 2, &tmpMV, &tmpMVDelta); tempSAD = BestSADs[SB_4x8_TL+block*2] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); } else { tempSAD = BestSADs[SB_4x8_TL]; // MV Constraint already added // Fill in MV for use in Predictor calc for next subblock pMV[0] = BestMVs[SB_4x8_TL]; } // Calc right predictor Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4+1], uRefFrame, &BestMVs[SB_4x8_TL+1+block*2], 1, 2, &tmpMV, &tmpMVDelta); tempSAD += BestSADs[SB_4x8_TL+1+block*2] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); tempSAD += pRDQM[3]; // 3 extra bits for 4x8 if (tempSAD < Block8x8Best[block]) { Block8x8Best[block] = tempSAD; Block8x8BestMode[block] = MODE_4x8; } // Finally, try 4 - 4x4 blocks // Calc UL block predictor if (block) { Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4], uRefFrame, &BestMVs[SB_4x4_TL+block*4], 1, 1, &tmpMV, &tmpMVDelta); tempSAD = BestSADs[SB_4x4_TL+block*4] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); } else { tempSAD = BestSADs[SB_4x4_TL]; // MV Constraint already added // Fill in MV for use in Predictor calc for next subblock pMV[0] = BestMVs[SB_4x4_TL]; } // Calc UR block predictor Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4+1], uRefFrame, &BestMVs[SB_4x4_TL+1+block*4], 1, 1, &tmpMV, &tmpMVDelta); tempSAD += BestSADs[SB_4x4_TL+1+block*4] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); // Calc LL block predictor Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4+2], uRefFrame, &BestMVs[SB_4x4_TL+2+block*4], 1, 1, &tmpMV, &tmpMVDelta); tempSAD += BestSADs[SB_4x4_TL+2+block*4] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); // Calc LR block predictor Estimate_One_MV_Predictor(uMB, block_subblock_mapping[block*4+3], uRefFrame, &BestMVs[SB_4x4_TL+3+block*4], 1, 1, &tmpMV, &tmpMVDelta); tempSAD += BestSADs[SB_4x4_TL+3+block*4] + MVConstraint(tmpMVDelta.iMVx, tmpMVDelta.iMVy, pRDQM); tempSAD += pRDQM[5]; // 5 extra bits for 4x4 if (tempSAD < Block8x8Best[block]) { Block8x8Best[block] = tempSAD; Block8x8BestMode[block] = MODE_4x4; m_pCurrentFrame->pMBData[uMB].SBType[block] = SBTYPE_4x4; } } // m_info.me_split_8x8s // Now write the chosen MVs to the MV buffer so that the MV prediction code // works correctly on the next iteration. offset = ((block&1)<<1) + (block&2) * uWidthIn4x4Blocks; switch (Block8x8BestMode[block]) { case MODE_8x8: // 8x8 // Copy one MV into four locations *(pMV + offset) = BestMVs[SB_8x8_TL+block]; *(pMV + offset + 1) = BestMVs[SB_8x8_TL+block]; *(pMV + offset + uWidthIn4x4Blocks) = BestMVs[SB_8x8_TL+block]; *(pMV + offset + uWidthIn4x4Blocks + 1) = BestMVs[SB_8x8_TL+block]; *(pRefIdxL0 + offset) = bestRefIdxs[SB_8x8_TL+block]; *(pRefIdxL0 + offset + 1) = bestRefIdxs[SB_8x8_TL+block]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks) = bestRefIdxs[SB_8x8_TL+block]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks + 1) = bestRefIdxs[SB_8x8_TL+block]; m_pCurrentFrame->pMBData[uMB].SBType[block] = SBTYPE_8x8; break; case MODE_8x4: // 8x4 // Copy two MVs into two locations each *(pMV + offset) = BestMVs[SB_8x4_TL+block*2]; *(pMV + offset + 1) = BestMVs[SB_8x4_TL+block*2]; *(pMV + offset + uWidthIn4x4Blocks) = BestMVs[SB_8x4_TL+1+block*2]; *(pMV + offset + uWidthIn4x4Blocks + 1) = BestMVs[SB_8x4_TL+1+block*2]; *(pRefIdxL0 + offset) = bestRefIdxs[SB_8x4_TL+block*2]; *(pRefIdxL0 + offset + 1) = bestRefIdxs[SB_8x4_TL+block*2]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks) = bestRefIdxs[SB_8x4_TL+1+block*2]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks + 1) = bestRefIdxs[SB_8x4_TL+1+block*2]; m_pCurrentFrame->pMBData[uMB].SBType[block] = SBTYPE_8x4; break; case MODE_4x8: // 4x8 // Copy two MVs into two locations each *(pMV + offset) = BestMVs[SB_4x8_TL+block*2]; *(pMV + offset + 1) = BestMVs[SB_4x8_TL+1+block*2]; *(pMV + offset + uWidthIn4x4Blocks) = BestMVs[SB_4x8_TL+block*2]; *(pMV + offset + uWidthIn4x4Blocks + 1) = BestMVs[SB_4x8_TL+1+block*2]; *(pRefIdxL0 + offset) = bestRefIdxs[SB_4x8_TL+block*2]; *(pRefIdxL0 + offset + 1) = bestRefIdxs[SB_4x8_TL+1+block*2]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks) = bestRefIdxs[SB_4x8_TL+block*2]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks + 1) = bestRefIdxs[SB_4x8_TL+1+block*2]; m_pCurrentFrame->pMBData[uMB].SBType[block] = SBTYPE_4x8; break; case MODE_4x4: // 4x4 // Copy four MVs into one location each *(pMV + offset) = BestMVs[SB_4x4_TL+block*4]; *(pMV + offset + 1) = BestMVs[SB_4x4_TL+1+block*4]; *(pMV + offset + uWidthIn4x4Blocks) = BestMVs[SB_4x4_TL+2+block*4]; *(pMV + offset + uWidthIn4x4Blocks + 1) = BestMVs[SB_4x4_TL+3+block*4]; *(pRefIdxL0 + offset) = bestRefIdxs[SB_4x4_TL+block*4]; *(pRefIdxL0 + offset + 1) = bestRefIdxs[SB_4x4_TL+1+block*4]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks) = bestRefIdxs[SB_4x4_TL+2+block*4]; *(pRefIdxL0 + offset + uWidthIn4x4Blocks + 1) = bestRefIdxs[SB_4x4_TL+3+block*4]; m_pCurrentFrame->pMBData[uMB].SBType[block] = SBTYPE_4x4; break; } } // OK, Now sum up the best coding of 8x8 blocks and compare it to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -