⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 motion_est.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 4 页
字号:
		
#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 + -