📄 umc_h264_me.cpp
字号:
MVPrev.iMVx, MVPrev.iMVy, SADPrev, MVFuture.iMVx, MVFuture.iMVy, SADFuture);#endif // BFRAME_PRINT_MVS#if defined BFRAME_FORCE_FUTURE_REFERENCE SADPrev = ME_MAX_SAD;#endif#if defined BFRAME_FORCE_PREVIOUS_REFERENCE SADFuture = ME_MAX_SAD;#endif } while (0); *puMBSAD = SADTemp; } else { // P Slice // Start Integer Search // Initial MB_type m_pCurrentFrame->pMBData[uMB].uMBType = MBTYPE_INTER;#ifdef P_EARLY_EXIT { Ipp32s iXType, iYType; Ipp8u *const pInterpBuf = m_pCurrentFrame->pMBEncodeBuffer + 256; Ipp8u *pRef = pRefPicList0[0]->m_pYPlane + m_pCurrentFrame->pMBOffsets[uMB].uLumaOffset + m_pCurrentFrame->y_line_shift; // Get the MV that could lead to a skip block Skip_MV_Predicted(uMB, &BestMVs[SB_16x16]); // MC it... pRef += SubpelMVAdjust(&BestMVs[SB_16x16], m_pCurrentFrame->uPitch, iXType, iYType); // interpolate copy the 16x16 block (*m_pCurrentFrame->InterpFunc)[iYType][iXType](pRef, pInterpBuf, m_pCurrentFrame->uPitch, 16, 16, 16); // if it's "good enough", just use it. Ipp32u tmpSAD = SAD16_P16(m_pCurrentFrame->m_pYPlane + m_pCurrentFrame->pMBOffsets[uMB].uLumaOffset + m_pCurrentFrame->y_line_shift, pInterpBuf, m_pCurrentFrame->uPitch); if (tmpSAD < PSkipMEThres[uQP]) { for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { pRefIdxL0[row*uWidthIn4x4Blocks + col] = 0; pRefIdxL1[row*uWidthIn4x4Blocks + col] = -1; pMVL0[row*uWidthIn4x4Blocks + col] = BestMVs[SB_16x16]; pMVL1[row*uWidthIn4x4Blocks + col] = NullMV; } } *puMBSAD = tmpSAD; m_pCurrentFrame->pMBData[uMB].uCBP4x4 = 0xffffff; } else {#endif VM_ASSERT(m_NumRefsInL0List); for (int k = 0; k < m_NumRefsInL0List; k++) { CMEOneMB_worker(uMB, k, pRefPicList0[k], iSearchHor, iSearchVer, false, bestRefIdxs, BestMVs, BestSADs, PredictedMV); } // Start Subpel Search CMESplitOneMB_P_Slice(uMB, puMBSAD, bestRefIdxs, BestMVs, BestSADs, PredictedMV);#ifdef P_EARLY_EXIT } }#endif }} // CMEOneMB////////////////////////////////////////////////////////////////////////////////// CMEOneMB_worker//////////////////////////////////////////////////////////////////////////////////// Perform MB Motion Estimation//// The MB ME steps are://// TBD - VSI - Describe new approach here....//// Possible uMBType values are (from enum MB_Type):// MBTYPE_INTRA, not used in this function// MBTYPE_INTER, 1 16x16 block// MBTYPE_INTER_8x8, 4 8x8 blocks (or subdivisions)// MBTYPE_INTER_8x8_REF0, 4 8x8 blocks (or subdivisions)// MBTYPE_FORWARD, B frame, forward (16x16 implied)// MBTYPE_BACKWARD, B frame, backward (16x16 implied)// MBTYPE_DIRECTvoid H264VideoEncoder::CMEOneMB_worker( Ipp32u uMB, T_RefIdx ref_idx, const H264EncoderFrame *pRefFrame, Ipp32s iSearchHor, Ipp32s iSearchVer, bool bBSlice, T_RefIdx bestRefIdxs[41], T_ECORE_MV BestMVs[41], Ipp32u BestSADs[41], T_ECORE_MV PredictedMV[41]){ T_EncodeMBOffsets *pMBOffset = &m_pCurrentFrame->pMBOffsets[uMB]; const Ipp8u *pCurrent = m_pCurrentFrame->m_pYPlane + pMBOffset->uLumaOffset + m_pCurrentFrame->y_line_shift; const Ipp8u *pPrev = pRefFrame->m_pYPlane + pMBOffset->uLumaOffset + m_pCurrentFrame->y_line_shift; const Ipp8u *pCur, *pRef; // Working pointers Ipp32s uPitch = m_pCurrentFrame->uPitch; Ipp32s uQP = m_pCurrentFrame->pMBData[uMB].uMBQP; Ipp16s *pRDQM = RDQM[uQP]; T_ECORE_MV BestMV16x16; Ipp32s uBestSAD16x16e, uBestSAD16x16NoRD; T_ECORE_MV tempPredictedMV[41]; bool bDone = false; Ipp32s xFactor, yFactor; Ipp32s xvec, yvec; Ipp32s block; Ipp32s StartX, StartY; Ipp32s maxleft, maxright, maxup, maxdown; Ipp32s left, right, up, down; const Ipp32s ME_MAX_SAD = INT_MAX >> 5; // Scaled down to allow sums of MAX without overflow. // FindBestOfInitial16x16 Ipp16u ThisSAD[41]; T_ECORE_BIGMV tmpMVDelta; Ipp32u tempSAD = 0; Ipp32u uRefFrame; unsigned int ref_constraint = RefConstraint(ref_idx, m_NumRefsInL0List, pRDQM); // max<dir> is the maximum number of pels that can be searched // in direction <dir>. These are signed value, ie, maxleft and // maxup will be negative or 0. maxleft = -(Ipp32s)((pMBOffset->uMVLimits & 0xff) >> 0); // pels maxright = (Ipp32s)((pMBOffset->uMVLimits & 0xff00) >> 8); // pels maxup = -(Ipp32s)((pMBOffset->uMVLimits & 0xff0000)>> 16);// pels maxdown = (Ipp32s)(pMBOffset->uMVLimits >> 24); // pels // Do the "Best of 4" analysis to find the best 16x16 integer search // starting point (and it's RD-Optimized distortion). Also returns // the predicted vectors for the 16x16 block. bDone = FindBestInitialMV( pCurrent, pPrev, uMB, bBSlice, BestMV16x16, // passed as ref and get initialized uBestSAD16x16e, // passed as ref and get initialized uBestSAD16x16NoRD, // resulting Distortion tempPredictedMV[SB_16x16], // passed as ref and get initialized maxleft, maxright, maxup, maxdown); if (!bDone) { // Starting with the "best of 5" results... StartX = (Ipp32s)BestMV16x16.iMVx; StartY = (Ipp32s)BestMV16x16.iMVy; left = MAX(maxleft, StartX - iSearchHor); left = MAX(left, -MAXINTVEC-1); // clip to Ipp8s range right = MIN(maxright, StartX + iSearchHor); right = MIN(right, MAXINTVEC); up = MAX(maxup, StartY - iSearchVer); up = MAX(up, -MAXINTVEC-1); down = MIN(maxdown, StartY + iSearchVer); down = MIN(down, MAXINTVEC); uRefFrame = (m_pCurrentFrame->pMBData[uMB].uMBType == MBTYPE_BACKWARD) ? 1 : 0; // Calc the predicted MV for the 8x8 blocks 0 Estimate_One_MV_Predictor(uMB, 0, uRefFrame, NULL, 2, 1, &tempPredictedMV[SB_8x8_TL], &tmpMVDelta); // Calc the predicted MV for the 8x16 block 0 Estimate_One_MV_Predictor(uMB, 0, uRefFrame, NULL, 2, 4, &tempPredictedMV[SB_8x16_L], &tmpMVDelta); // Calc the predicted MV for the 16x8 block 0 Estimate_One_MV_Predictor(uMB, 0, uRefFrame, NULL, 4, 2, &tempPredictedMV[SB_16x8_T], &tmpMVDelta); // Calc the predicted MV for the 8x16 block 1 Estimate_One_MV_Predictor(uMB, 2, uRefFrame, NULL, 2, 4, &tempPredictedMV[SB_8x16_R], &tmpMVDelta); // Calc the predicted MV for the 16x8 block 1 Estimate_One_MV_Predictor(uMB, 8, uRefFrame, NULL, 4, 2, &tempPredictedMV[SB_16x8_B], &tmpMVDelta); if (m_info.me_split_8x8s) // Split 8x8s { T_ECORE_MV temp_BestMVs[41]; Ipp32u temp_BestSADs[41]; T_RefIdx temp_bestRefIdxs[41]; T_ECORE_MV NullMV = {0, 0}; int block; for (block = 0; block < 41; block++) { temp_BestSADs[block] = ME_MAX_SAD; temp_BestMVs[block] = NullMV; temp_bestRefIdxs[block] = -1; } // Calc the predicted MV for the 4x4 & 4x8 & 8x4 blocks 0 Estimate_One_MV_Predictor(uMB, 0, uRefFrame, NULL, 1, 1, &tempPredictedMV[SB_4x4_TL], &tmpMVDelta); tempPredictedMV[SB_4x8_TL] = tempPredictedMV[SB_4x4_TL]; tempPredictedMV[SB_8x4_TL] = tempPredictedMV[SB_8x8_TL]; // 8x4 same as 8x8 yFactor = SubPelFactor*up; for (yvec = up; yvec <= down; ++yvec, yFactor += SubPelFactor) { xFactor = SubPelFactor*left; for (xvec = left; xvec <= right; ++xvec, xFactor += SubPelFactor) { pCur = pCurrent; pRef = MVADJUST(pPrev, uPitch, xvec, yvec); SAD16SB16 (pCur, pRef, ThisSAD, uPitch); ThisSAD[SB_4x4_TL] += ref_constraint/4 + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_4x4_TL].iMVx, yFactor - tempPredictedMV[SB_4x4_TL].iMVy, pRDQM); ThisSAD[SB_4x8_TL] += ref_constraint/2 + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_4x8_TL].iMVx, yFactor - tempPredictedMV[SB_4x8_TL].iMVy, pRDQM); ThisSAD[SB_8x4_TL] += ref_constraint/2 + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_8x4_TL].iMVx, yFactor - tempPredictedMV[SB_8x4_TL].iMVy, pRDQM); ThisSAD[SB_8x8_TL] += ref_constraint + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_8x8_TL].iMVx, yFactor - tempPredictedMV[SB_8x8_TL].iMVy, pRDQM); ThisSAD[SB_8x16_L] += ref_constraint + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_8x16_L].iMVx, yFactor - tempPredictedMV[SB_8x16_L].iMVy, pRDQM); ThisSAD[SB_16x8_T] += ref_constraint + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_16x8_T].iMVx, yFactor - tempPredictedMV[SB_16x8_T].iMVy, pRDQM); ThisSAD[SB_16x16] += ref_constraint + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_16x16].iMVx, yFactor - tempPredictedMV[SB_16x16].iMVy, pRDQM); ThisSAD[SB_8x16_R] += ref_constraint + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_8x16_R].iMVx, yFactor - tempPredictedMV[SB_8x16_R].iMVy, pRDQM); ThisSAD[SB_16x8_B] += ref_constraint + (Ipp16u)MVConstraint(xFactor - tempPredictedMV[SB_16x8_B].iMVx, yFactor - tempPredictedMV[SB_16x8_B].iMVy, pRDQM); // if 8x8 is better then SADComp41(ThisSAD, temp_BestSADs, temp_BestMVs, ref_idx, temp_bestRefIdxs, tempPredictedMV, tempPredictedMV, xvec, yvec, 0, 32); SADComp41(ThisSAD, BestSADs, BestMVs, ref_idx, bestRefIdxs, tempPredictedMV, PredictedMV, xvec, yvec, 32, 41); } // for xvec } // for yvec for (block = 0; block < 4; block++) { if (ThisSAD[SB_8x8_TL + block] < BestSADs[SB_8x8_TL + block]) { Move_ME_Info(temp_BestSADs, BestSADs, BestMVs, temp_BestMVs, ref_idx, bestRefIdxs, tempPredictedMV, PredictedMV, SB_4x4_TL+block*4, SB_4x4_TL+block*4 + 4); Move_ME_Info(temp_BestSADs, BestSADs, BestMVs, temp_BestMVs, ref_idx, bestRefIdxs, tempPredictedMV, PredictedMV, SB_8x4_TL+block*2, SB_8x4_TL+block*2 + 2); Move_ME_Info(temp_BestSADs, BestSADs, BestMVs, temp_BestMVs, ref_idx, bestRefIdxs, tempPredictedMV, PredictedMV, SB_4x8_TL+block*2, SB_4x8_TL+block*2 + 2); } } } else { // Don't split 8x8s yFactor = SubPelFactor*up; for (yvec = up; yvec <= down; ++yvec, yFactor += SubPelFactor) { xFactor = SubPelFactor*left; for (xvec = left; xvec <= right; ++xvec, xFactor += SubPelFactor) { // Add in the approx RD cost of the MV diff for block zero tempSAD = MVConstraint(xFactor - PredictedMV[SB_8x8_TL].iMVx, yFactor - PredictedMV[SB_8x8_TL].iMVy, pRDQM) + ref_constraint; pCur = pCurrent; pRef = MVADJUST(pPrev, uPitch, xvec, yvec); SAD16SB4 (pCur, pRef, ThisSAD, uPitch); for (block = 32; block < 36; ++block) { // 4 - 8x8 blocks tempSAD += (Ipp32u)ThisSAD[block-32]; // Accumulate SAD and MVs for 8x8 blocks if (tempSAD < BestSADs[block]) { BestSADs[block] = tempSAD; BestMVs[block].iMVx = (Ipp8s)xvec*SubPelFactor; BestMVs[block].iMVy = (Ipp8s)yvec*SubPelFactor; bestRefIdxs[block] = ref_idx; PredictedMV[block] = tempPredictedMV[block]; } tempSAD = 0; } // block// Unroll the loop; removes table lookups tempSAD = MVConstraint(xFactor - PredictedMV[SB_8x16_L].iMVx, yFactor - PredictedMV[SB_8x16_L].iMVy, pRDQM) + ref_constraint; tempSAD += ((Ipp32u)ThisSAD[0]+(Ipp32u)ThisSAD[2]); if (tempSAD < BestSADs[SB_8x16_L]) { BestSADs[SB_8x16_L] = tempSAD; BestMVs[SB_8x16_L].iMVx = (Ipp8s)xvec*SubPelFactor; BestMVs[SB_8x16_L].iMVy = (Ipp8s)yvec*SubPelFactor; bestRefIdxs[SB_8x16_L] = ref_idx; PredictedMV[SB_8x16_L] = tempPredictedMV[SB_8x16_L]; } tempSAD = MVConstraint(xFactor - PredictedMV[SB_8x16_R].iMVx, yFactor - PredictedMV[SB_8x16_R].iMVy, pRDQM) + ref_constraint; tempSAD += ((Ipp32u)ThisSAD[1]+(Ipp32u)ThisSAD[3]); if (tempSAD < BestSADs[SB_8x16_R]) { BestSADs[SB_8x16_R] = tempSAD; BestMVs[SB_8x16_R].iMVx = (Ipp8s)xvec*SubPelFactor; BestMVs[SB_8x16_R].iMVy = (Ipp8s)yvec*SubPelFactor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -