motion_est.c
来自「mpeg4代码,比较具体」· C语言 代码 · 共 2,172 行 · 第 1/5 页
C
2,172 行
} CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);/* top right neighbour, if allowed */ if (!MVzero(pmv[3])) if (!MVequal(pmv[3], prevMB->mvs[0])) if (!MVequal(pmv[3], pmv[0])) if (!MVequal(pmv[3], pmv[1])) if (!MVequal(pmv[3], pmv[2])) { if (!(MotionFlags & PMV_HALFPEL16)) { pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); } CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y); } } if ((MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ ) iMinSAD -= MV16_00_BIAS;/* Step 6: If MinSAD <= thresa goto Step 10. If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10. */ if ((iMinSAD <= threshA) || (MVequal(*currMV, prevMB->mvs[0]) && ((int32_t) iMinSAD < prevMB->sad16))) { if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine; if (MotionFlags & PMV_EARLYSTOP16) goto PMVfast16_Terminate_with_Refine; }/************ (Diamond Search) **************//* Step 7: Perform Diamond search, with either the small or large diamond. If Found=2 only examine one Diamond pattern, and afterwards goto step 10 Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond. If center then goto step 10. Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center. Refine by using small diamond and goto step 10. */ if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = Square16_MainSearch; else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamond16_MainSearch; else MainSearchPtr = Diamond16_MainSearch; backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH *//* default: use best prediction as starting point for one call of PMVfast_MainSearch */ iSAD = (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound); if (iSAD < iMinSAD) { *currMV = newMV; iMinSAD = iSAD; } if (MotionFlags & PMV_EXTSEARCH16) {/* extended: search (up to) two more times: orignal prediction and (0,0) */ if (!(MVequal(pmv[0], backupMV))) { iSAD = (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, center_x, center_y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound); if (iSAD < iMinSAD) { *currMV = newMV; iMinSAD = iSAD; } } if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) { iSAD = (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound); if (iSAD < iMinSAD) { *currMV = newMV; iMinSAD = iSAD; } } }/* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.*/ PMVfast16_Terminate_with_Refine: if (MotionFlags & PMV_HALFPELREFINE16) /* perform final half-pel step */ iMinSAD = Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV, iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth); PMVfast16_Terminate_without_Refine: currPMV->x = currMV->x - center_x; currPMV->y = currMV->y - center_y; return iMinSAD;}int32_tDiamond8_MainSearch(const uint8_t * const pRef, const uint8_t * const pRefH, const uint8_t * const pRefV, const uint8_t * const pRefHV, const uint8_t * const cur, const int x, const int y, const int32_t start_x, const int32_t start_y, int32_t iMinSAD, VECTOR * const currMV, const int center_x, const int center_y, const int32_t min_dx, const int32_t max_dx, const int32_t min_dy, const int32_t max_dy, const int32_t iEdgedWidth, const int32_t iDiamondSize, const int32_t iFcode, const int32_t iQuant, int iFound){/* Do a diamond search around given starting point, return SAD of best */ int32_t iDirection = 0; int32_t iDirectionBackup; int32_t iSAD; VECTOR backupMV; backupMV.x = start_x; backupMV.y = start_y;/* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */ CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1); CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2); CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3); CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4); if (iDirection) { while (!iFound) { iFound = 1; backupMV = *currMV; /* since iDirection!=0, this is well defined! */ iDirectionBackup = iDirection; if (iDirectionBackup != 2) CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y, 1); if (iDirectionBackup != 1) CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y, 2); if (iDirectionBackup != 4) CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize, 3); if (iDirectionBackup != 3) CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize, 4); } } else { currMV->x = start_x; currMV->y = start_y; } return iMinSAD;}int32_tSquare8_MainSearch(const uint8_t * const pRef, const uint8_t * const pRefH, const uint8_t * const pRefV, const uint8_t * const pRefHV, const uint8_t * const cur, const int x, const int y, const int32_t start_x, const int32_t start_y, int32_t iMinSAD, VECTOR * const currMV, const int center_x, const int center_y, const int32_t min_dx, const int32_t max_dx, const int32_t min_dy, const int32_t max_dy, const int32_t iEdgedWidth, const int32_t iDiamondSize, const int32_t iFcode, const int32_t iQuant, int iFound){/* Do a square search around given starting point, return SAD of best */ int32_t iDirection = 0; int32_t iSAD; VECTOR backupMV; backupMV.x = start_x; backupMV.y = start_y;/* It's one search with full square pattern, and new parts for all following diamonds *//* new direction are extra, so 1-4 is normal diamond 537 1*2 648 */ CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1); CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2); CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3); CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4); CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); if (iDirection) { while (!iFound) { iFound = 1; backupMV = *currMV; switch (iDirection) { case 1: CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y, 1); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); break; case 2: CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y, 2); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); break; case 3: CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize, 4); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); break; case 4: CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize, 3); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); break; case 5: CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y, 1); CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize, 3); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); break; case 6: CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y, 2); CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize, 3); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); break; case 7: CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y, 1); CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize, 4); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); break; case 8: CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y, 2); CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize, 4); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); break; default: CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y, 1); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y, 2); CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize, 3); CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize, 4); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y - iDiamondSize, 5); CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y + iDiamondSize, 6); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y - iDiamondSize, 7); CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y + iDiamondSize, 8); break; } } } else { currMV->x = start_x; currMV->y = start_y; } return iMinSAD;}int32_tHalfpel8_Refine_c(const uint8_t * const pRef, const uint8_t * const pRefH, const uint8_t * const pRefV, const uint8_t * const pRefHV, const uint8_t * const cur, const int x, const int y, VECTOR * const currMV, int32_t iMinSAD, const int center_x, const int center_y, const int32_t min_dx, const int32_t max_dx, const int32_t min_dy, const int32_t max_dy, const int32_t iFcode, const int32_t iQuant, const int32_t iEdgedWidth){/* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */ int32_t iSAD; VECTOR backupMV = *currMV; CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1); CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1); CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1); CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y); CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y); CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1); CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1); CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1); return iMinSAD;}#define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)int32_tPMVfastSearch8(const uint8_t * const pRef, const uint8_t * const pRefH, const uint8_t * const pRefV, const uint8_t * const pRefHV, const IMAGE * const pCur, const int x, const int y, const int start_x, const int start_y, const int center_x, const int center_y, const uint32_t MotionFlags, const uint32_t iQuant, const uint32_t iFcode, const MBParam * const pParam, const MACROBLOCK * const pMBs, const MACROBLOCK * const prevMBs, VECTOR * const currMV, VECTOR * const currPMV)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?