📄 motion_est.c
字号:
#define NOCHECK_MV8_CANDIDATE(X,Y) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \}#define CHECK_MV8_CANDIDATE(X,Y) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \}#define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \}#define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \}/* too slow and not fully functional at the moment *//*int32_t ZeroSearch16( 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 uint32_t MotionFlags, MBParam * const pParam, MACROBLOCK * const pMBs, VECTOR * const currMV, VECTOR * const currPMV){ const int32_t iEdgedWidth = pParam->edged_width; const int32_t iQuant = pParam->quant; const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth; int32_t iSAD; int32_t pred_x,pred_y; get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y); iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); if (iSAD <= iQuant * 96) iSAD -= MV16_00_BIAS; currMV->x = 0; currMV->y = 0; currPMV->x = -pred_x; currPMV->y = -pred_y; return iSAD;}*/int32_t Diamond16_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, int32_t startx, int32_t starty, int32_t iMinSAD, VECTOR * const currMV, const VECTOR * const pmv, 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 iSAD; VECTOR backupMV; backupMV.x = startx; backupMV.y = starty; /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */ CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4); if (iDirection) while (!iFound) { iFound = 1; backupMV=*currMV; if ( iDirection != 2) CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1); if ( iDirection != 1) CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2); if ( iDirection != 4) CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3); if ( iDirection != 3) CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4); } else { currMV->x = startx; currMV->y = starty; } return iMinSAD;}int32_t Square16_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, int32_t startx, int32_t starty, int32_t iMinSAD, VECTOR * const currMV, const VECTOR * const pmv, 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 = startx; backupMV.y = starty; /* 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_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); if (iDirection) while (!iFound) { iFound = 1; backupMV=*currMV; switch (iDirection) { case 1: CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); break; case 2: CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); break; case 3: CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); break; case 4: CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); break; case 5: CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); break; case 6: CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); break; case 7: CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); break; case 8: CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); break; default: CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3); CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5); CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7); CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8); break; } } else { currMV->x = startx; currMV->y = starty; } return iMinSAD;}int32_t Full16_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, int32_t startx, int32_t starty, int32_t iMinSAD, VECTOR * const currMV, const VECTOR * const pmv, 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){ int32_t iSAD; int32_t dx,dy; VECTOR backupMV; backupMV.x = startx; backupMV.y = starty; for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize) for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize) NOCHECK_MV16_CANDIDATE(dx,dy); return iMinSAD;}int32_t Full8_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, int32_t startx, int32_t starty, int32_t iMinSAD, VECTOR * const currMV, const VECTOR * const pmv, 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){ int32_t iSAD; int32_t dx,dy; VECTOR backupMV; backupMV.x = startx; backupMV.y = starty; for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize) for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize) NOCHECK_MV8_CANDIDATE(dx,dy); return iMinSAD;}int32_t Halfpel16_Refine( 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 VECTOR * const pmv, 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_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1); CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y-1); CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1); CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y); CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y); CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1); CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y+1); CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1); return iMinSAD;}#define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)int32_t PMVfastSearch16( 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 uint32_t MotionFlags, const MBParam * const pParam, MACROBLOCK * const pMBs, VECTOR * const currMV, VECTOR * const currPMV){ const uint32_t iWcount = pParam->mb_width; const int32_t iFcode = pParam->fixed_code; const int32_t iQuant = pParam->quant; const int32_t iWidth = pParam->width; const int32_t iHeight = pParam->height; const int32_t iEdgedWidth = pParam->edged_width; const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth; int32_t iDiamondSize; int32_t min_dx; int32_t max_dx; int32_t min_dy; int32_t max_dy; int32_t iFound; VECTOR newMV; VECTOR backupMV; /* just for PMVFAST */ VECTOR pmv[4]; int32_t psad[4]; MACROBLOCK * const pMB = pMBs + x + y * iWcount; static int32_t threshA,threshB; int32_t bPredEq; int32_t iMinSAD,iSAD;/* Get maximum range */ get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight, iFcode);/* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */ if (!(MotionFlags & PMV_HALFPEL16 )) { min_dx = EVEN(min_dx); max_dx = EVEN(max_dx); min_dy = EVEN(min_dy); max_dy = EVEN(max_dy); } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */ bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad); if ((x==0) && (y==0) ) { threshA = 512; threshB = 1024; } else { threshA = psad[0]; threshB = threshA+256; if (threshA< 512) threshA = 512; if (threshA>1024) threshA = 1024; if (threshB>1792) threshB = 1792; } iFound=0; /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion vector of the median. If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 */ if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) ) iFound=2;/* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. Otherwise select large Diamond Search. */ if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) ) iDiamondSize=1; // halfpel! else iDiamondSize=2; // halfpel! if (!(MotionFlags & PMV_HALFPELDIAMOND16) ) iDiamondSize*=2;/* Step 4: Calculate SAD around the Median prediction. MinSAD=SAD If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10. If SAD<=256 goto Step 10. */ // Prepare for main loop *currMV=pmv[0]; /* current best := prediction */ if (!(MotionFlags & PMV_HALFPEL16 )) { /* This should NOT be necessary! */ currMV->x = EVEN(currMV->x); currMV->y = EVEN(currMV->y); } if (currMV->x > max_dx) { currMV->x=max_dx; } if (currMV->x < min_dx) { currMV->x=min_dx; } if (currMV->y > max_dy) { currMV->y=max_dy; } if (currMV->y < min_dy)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -