📄 motest.c
字号:
///////////* * mesFindMotionBlock: * * Parameters: * blk Buffer pointers and parameters related to the block * pMeProf Parameters for controlling ME * retSad The minimum SAD of the block, for the best MV * * Function: * Find the best motion vector for 1 block, of any possible size * * Returns: * Best motion vector *////// LOW_COMPLEX_PROF3static motVec_s mesFindMotionBlock_fast(mbPart_s *mbPart, meProfile_s *pMeProf, int *retSad){ motVec_s bestVec, myBestVec; int bestSad, sad0; int neighborSads[5], fastHalfPixel; LC3_s *plc3=mbPart->plc3; int do_qpel=0; int old_bestSad, change_bestSad; //////////////// // y has been upsampled bestVec.x = 0; bestVec.y = 0; // SAD for zero vector sad0 = findSadPT(mbPart, 0, 0, INT_MAX); bestSad = sad0; // SAD for predicted vector if ((pMeProf->estVec4[0] | pMeProf->estVec4[1]) != 0) { int estMvX, estMvY; int tmpSad; estMvX = pMeProf->estVec4[0]; estMvY = pMeProf->estVec4[1]; // Although it could be checked again if it is in the search range, // but having a check up-front can speedup the speed, // in sparse search, this could be an additional check point tmpSad = findSadPT(mbPart, estMvX, estMvY, bestSad); if (tmpSad < bestSad) { bestSad = tmpSad; bestVec.x = (int16) estMvX; bestVec.y = (int16) estMvY; } } // Integer pel search fastHalfPixel = mesMultiStepSearch (mbPart, pMeProf, & bestVec, & bestSad, neighborSads); myBestVec = bestVec; // is bestVec (0, 0), but (0, 0) not in the search range? // this refinement search at the center seems to give better performance // at low bit rate, but not high bit rate, if ((bestVec.x == 0) && (bestVec.y == 0) && ((pMeProf->p0[0] >= 8) || (pMeProf->p1[0] <= -8)) && ((pMeProf->p0[1] >= 8) || (pMeProf->p1[1] <= -8))) { meProfile_s origProf; origProf = *pMeProf; // I do not like your search ranges, (0, 0) not in the range, but better! pMeProf->p0[0] = -8; pMeProf->p1[0] = 8; pMeProf->p0[1] = -8; pMeProf->p1[1] = 8; // Integer pel search mesMultiStepSearch(mbPart, pMeProf, & bestVec, & bestSad, neighborSads); } mesGradientSearch(mbPart, pMeProf, & bestVec, & bestSad); old_bestSad=bestSad; if ((mbPart->profile == PROF_CODING_SPEED) && (myBestVec.x == bestVec.x && myBestVec.y == bestVec.y && fastHalfPixel)) { // we do fast search only when there are 5 SADs available, and // minimal SAD sits in the middle, seems to be still very probable motVec_s oldBestVec; int direction[2], mySad, oldSad; int halfPixelSads[3][3]; // 1/2 and 1/4 pixel search oldBestVec = bestVec; oldSad = bestSad; mySad = bestSad; fastHalfPixel = mesPredictHalfPixel (mbPart, neighborSads, (int *) halfPixelSads, & bestVec, & bestSad, direction); } if (! fastHalfPixel) matchBlockDiamond(mbPart, 2, & bestVec, & bestSad, 0); change_bestSad=old_bestSad-bestSad; do_qpel+=(change_bestSad>plc3->thre_change[plc3->mode]); if (plc3->mode==MOT_16x16) { do_qpel+=1; } else { do_qpel += plc3->do_qpel_mode_2_3; } old_bestSad=bestSad; if (do_qpel>=2) // do quarter pel when **both** heuristics are satisfied { if (mbPart->profile == PROF_CODING_SPEED) matchBlockDiamond(mbPart, 1, & bestVec, & bestSad, 0); else { bestSad = INT_MAX; matchBlockDiamond(mbPart, 1, & bestVec, & bestSad, 1); } } change_bestSad=old_bestSad-bestSad; if ( ( plc3->qp>TH_QP2 ) && ( (plc3->mode==MOT_16x8) || (plc3->mode==MOT_8x16) ) ) { if (plc3->cnt!=plc3->old_cnt) { // diff mb plc3->old_cnt=plc3->cnt; if ( change_bestSad< TH_QPEL ) plc3->do_qpel_mode_2_3=0; } } *retSad = bestSad; return bestVec;}/////// LOW_COMPLEX_PROF3/* * mesFindMotionBlock: * * Parameters: * blk Buffer pointers and parameters related to the block * pMeProf Parameters for controlling ME * retSad The minimum SAD of the block, for the best MV * * Function: * Find the best motion vector for 1 block, of any possible size * * Returns: * Best motion vector */static motVec_s mesFindMotionBlock(mbPart_s *mbPart, meProfile_s *pMeProf, int *retSad){ motVec_s bestVec, myBestVec; int bestSad, sad0; int neighborSads[5], fastHalfPixel; // y has been upsampled bestVec.x = 0; bestVec.y = 0; // SAD for zero vector sad0 = findSadPT(mbPart, 0, 0, INT_MAX); bestSad = sad0; // SAD for predicted vector if ((pMeProf->estVec4[0] | pMeProf->estVec4[1]) != 0) { int estMvX, estMvY; int tmpSad; estMvX = pMeProf->estVec4[0]; estMvY = pMeProf->estVec4[1]; // Although it could be checked again if it is in the search range, // but having a check up-front can speedup the speed, // in sparse search, this could be an additional check point tmpSad = findSadPT(mbPart, estMvX, estMvY, bestSad); if (tmpSad < bestSad) { bestSad = tmpSad; bestVec.x = (int16) estMvX; bestVec.y = (int16) estMvY; } } // Integer pel search fastHalfPixel = mesMultiStepSearch (mbPart, pMeProf, & bestVec, & bestSad, neighborSads); myBestVec = bestVec; // is bestVec (0, 0), but (0, 0) not in the search range? // this refinement search at the center seems to give better performance // at low bit rate, but not high bit rate, if ((bestVec.x == 0) && (bestVec.y == 0) && ((pMeProf->p0[0] >= 8) || (pMeProf->p1[0] <= -8)) && ((pMeProf->p0[1] >= 8) || (pMeProf->p1[1] <= -8))) { meProfile_s origProf; origProf = *pMeProf; // I do not like your search ranges, (0, 0) not in the range, but better! pMeProf->p0[0] = -8; pMeProf->p1[0] = 8; pMeProf->p0[1] = -8; pMeProf->p1[1] = 8; // Integer pel search mesMultiStepSearch(mbPart, pMeProf, & bestVec, & bestSad, neighborSads); } mesGradientSearch(mbPart, pMeProf, & bestVec, & bestSad); if ((mbPart->profile == PROF_CODING_SPEED) && (myBestVec.x == bestVec.x && myBestVec.y == bestVec.y && fastHalfPixel)) { // we do fast search only when there are 5 SADs available, and // minimal SAD sits in the middle, seems to be still very probable motVec_s oldBestVec; int direction[2], mySad, oldSad; int halfPixelSads[3][3]; // 1/2 and 1/4 pixel search oldBestVec = bestVec; oldSad = bestSad; mySad = bestSad; fastHalfPixel = mesPredictHalfPixel (mbPart, neighborSads, (int *) halfPixelSads, & bestVec, & bestSad, direction); } if (! fastHalfPixel) matchBlockDiamond(mbPart, 2, & bestVec, & bestSad, 0); if (mbPart->profile == PROF_CODING_SPEED) matchBlockDiamond(mbPart, 1, & bestVec, & bestSad, 0); else { bestSad = INT_MAX; matchBlockDiamond(mbPart, 1, & bestVec, & bestSad, 1); } *retSad = bestSad; return bestVec;}/* * mesDetermineSearchRegion: * * Parameters: * * Function: * Determine in which range the search should be performed. * The search center changes from MB to MB, but the size of the search * area will always be (2*range + 1) * (2*range + 1). * * Returns: * - */static void mesDetermineSearchRegion(meProfile_s *pMeProf, motVec_s *predVec, macroblock_s *pMb, mbPart_s *mbPart){ int i; int ctr[2], sizes[2], blkStart[2]; int blkAddr; blkAddr = mbPart->y0 * 4 + mbPart->x0; blkStart[0] = (pMb->idxX * BLK_PER_MB + mbPart->x0) * BLK_SIZE; blkStart[1] = (pMb->idxY * BLK_PER_MB + mbPart->y0) * BLK_SIZE; sizes[0] = mbPart->width; sizes[1] = mbPart->height; ctr[0] = predVec->x; ctr[1] = predVec->y; pMeProf->predVec = *predVec; // i = 0, x, i = 1, y for (i = 0; i < 2; i ++) { // lower and upper limits, convert to quarter pixel precision pMeProf->vecLmt0[i] = (int16) (4 * (pMeProf->area0[i] - blkStart[i])); pMeProf->vecLmt1[i] = (int16) (4 * (pMeProf->area1[i] - blkStart[i] - sizes[i])); if (i == 1) { /* Make sure we don't violate MV vertical range limitation */ if (pMeProf->vecLmt0[i] < (-pMeProf->maxVerticalMvRange+MBK_SIZE)*4) pMeProf->vecLmt0[i] = (int16)((-pMeProf->maxVerticalMvRange+MBK_SIZE)*4); if (pMeProf->vecLmt1[i] > (pMeProf->maxVerticalMvRange-MBK_SIZE-1)*4) pMeProf->vecLmt1[i] = (int16)((pMeProf->maxVerticalMvRange-MBK_SIZE-1)*4); } pMeProf->estVec4[i] = (int16) ((ctr[i] + 2) & (~3)); if (pMeProf->estVec4[i] < pMeProf->vecLmt0[i]) pMeProf->estVec4[i] = pMeProf->vecLmt0[i]; if (pMeProf->estVec4[i] > pMeProf->vecLmt1[i]) pMeProf->estVec4[i] = pMeProf->vecLmt1[i]; if (pMeProf->searchCtrFlag != CENTER_PRED_MV) { ctr[i] = (pMeProf->searchCtrs[blkAddr][i] + ctr[i]) >> 1; // ctr[i] = pEncState->searchCtrs[blkAddr][i]; } // Set nominal range of the motion, and the hard limits on the motion ctr[i] = (ctr[i] + 2) & (~3); // the search area will always be (2*range + 1) * (2*range + 1) pMeProf->p0[i] = (int16) (ctr[i] - mbPart->range); if (pMeProf->p0[i] < pMeProf->vecLmt0[i]) pMeProf->p0[i] = pMeProf->vecLmt0[i]; if ((pMeProf->p0[i] + mbPart->range * 2) > pMeProf->vecLmt1[i]) pMeProf->p0[i] = (int16) (pMeProf->vecLmt1[i] - 2 * mbPart->range); pMeProf->p1[i] =(int16) (pMeProf->p0[i] + 2 * mbPart->range); }}/* * mesBlockLazyMatch: * * Parameters: * sadsPtr Pointer to buffer storing SAD values * mode Block mode * bestLazyMode Mode with the best match * * Function: * Find the best match found so far. * * Returns: * Minimal SAD for the MB or sub-MB being predicted. */int mesBlockLazyMatch(int16 *sadsPtr, int mode, int *bestLazyMode){ int m; int bestSad, partSad; *bestLazyMode = MOT_16x16; bestSad = 0; // we address blkSADs as 1-D array here switch (mode) { case MOT_4x4: bestSad = sadsPtr[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -