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

📄 motion_est.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	{			currMV->y=min_dy;	}		iMinSAD = sad16( cur, 			 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),			 iEdgedWidth, MV_MAX_ERROR);  	iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;		if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )	{				if (MotionFlags & PMV_QUICKSTOP16) 			goto PMVfast16_Terminate_without_Refine;		if (MotionFlags & PMV_EARLYSTOP16)			goto PMVfast16_Terminate_with_Refine;	}/*    Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.    Also calculate (0,0) but do not subtract offset.    Let MinSAD be the smallest SAD up to this point.    If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ************/// (0,0) is always possible	CHECK_MV16_ZERO;// previous frame MV is always possible	CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);	// left neighbour, if allowed	if (x != 0) 	{		if (!(MotionFlags & PMV_HALFPEL16 ))		{	pmv[1].x = EVEN(pmv[1].x);		pmv[1].y = EVEN(pmv[1].y);		}		CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);			}// top neighbour, if allowed	if (y != 0)	{			if (!(MotionFlags & PMV_HALFPEL16 ))		{	pmv[2].x = EVEN(pmv[2].x);		pmv[2].y = EVEN(pmv[2].y);		}		CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);	// top right neighbour, if allowed		if (x != (iWcount-1))		{			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);		}	}/* 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,pMB->mvs[0]) && (iMinSAD < pMB->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. */	backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH *//* default: use best prediction as starting point for one call of PMVfast_MainSearch */	iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,					  x, y, 					  currMV->x, currMV->y, iMinSAD, &newMV, 					  pmv, 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 = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,							  x, y, 							  pmv[0].x, pmv[0].y, iMinSAD, &newMV, 							  pmv, 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 = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,							  x, y, 							  0, 0, iMinSAD, &newMV, 							  pmv, 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, 				  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);PMVfast16_Terminate_without_Refine:	currPMV->x = currMV->x - pmv[0].x;	currPMV->y = currMV->y - pmv[0].y;	return iMinSAD;}int32_t Diamond8_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_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!				if ( iDirection != 2) 				CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);			if ( iDirection != 1) 				CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);			if ( iDirection != 4) 				CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);			if ( iDirection != 3) 				CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);		}	else	{			currMV->x = startx;		currMV->y = starty;	}	return iMinSAD;}int32_t Halfpel8_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_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_t PMVfastSearch8(					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, int start_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*8 + y*8*iEdgedWidth;	int32_t iDiamondSize;	int32_t min_dx;	int32_t max_dx;	int32_t min_dy;	int32_t max_dy;			VECTOR pmv[4];	int32_t psad[4];	VECTOR newMV;	VECTOR backupMV;		MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;	static int32_t threshA,threshB;    	int32_t iFound,bPredEq;    	int32_t iMinSAD,iSAD;	int32_t iSubBlock = ((y&1)<<1) + (x&1);/* Get maximum range */	get_range(&min_dx, &max_dx, &min_dy, &max_dy,		  x, y, 8, iWidth, iHeight, iFcode);/* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */	if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))	{ min_dx = EVEN(min_dx);	max_dx = EVEN(max_dx);	min_dy = EVEN(min_dy);	max_dy = EVEN(max_dy); 	}		/* because we might use IF (dx>max_dx) THEN dx=max_dx; */			bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);	if ((x==0) && (y==0) )	{		threshA =  512/4;		threshB = 1024/4;		}	else	{		threshA = psad[0]/4;			/* good estimate */		threshB = threshA+256/4;		if (threshA< 512/4) threshA =  512/4;                if (threshA>1024/4) threshA = 1024/4;         	if (threshB>1792/4) threshB = 1792/4; 	}	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[iSubBlock]) ) )		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/4) || (bPredEq) ) 		iDiamondSize=1;	// 1 halfpel!	else		iDiamondSize=2;	// 2 halfpel = 1 full pixel!	if (!(MotionFlags & PMV_HALFPELDIAMOND8) )		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->x=start_x;		/* start with mv16 */	currMV->y=start_y;				iMinSAD = sad8( cur, 			get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),			iEdgedWidth);  	iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;		if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )	{		if (MotionFlags & PMV_QUICKSTOP16) 			goto PMVfast8_Terminate_without_Refine;		if (MotionFlags & PMV_EARLYSTOP16)			goto PMVfast8_Terminate_with_Refine;	}/*    Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.    Also calculate (0,0) but do not subtract offset.    Let MinSAD be the smallest SAD up to this point.    If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ************/// the prediction might be even better than mv16	CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);// (0,0) is always possible	CHECK_MV8_ZERO;// previous frame MV is always possible	CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);	// left neighbour, if allowed	if (psad[1] != MV_MAX_ERROR) 	{		if (!(MotionFlags & PMV_HALFPEL8 ))			{	pmv[1].x = EVEN(pmv[1].x);			pmv[1].y = EVEN(pmv[1].y);		}		CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);			}// top neighbour, if allowed	if (psad[2] != MV_MAX_ERROR) 	{			if (!(MotionFlags & PMV_HALFPEL8 ))		{	pmv[2].x = EVEN(pmv[2].x);		pmv[2].y = EVEN(pmv[2].y);		}		CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);	// top right neighbour, if allowed		if (psad[3] != MV_MAX_ERROR) 		{			if (!(MotionFlags & PMV_HALFPEL8 ))			{	pmv[3].x = EVEN(pmv[3].x);			pmv[3].y = EVEN(pmv[3].y);			}			CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);		}	}/* 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,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )	{			if (MotionFlags & PMV_QUICKSTOP16) 			goto PMVfast8_Terminate_without_Refine;		if (MotionFlags & PMV_EARLYSTOP16)			goto PMVfast8_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. */	backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH *//* default: use best prediction as starting point for one call of PMVfast_MainSearch */	iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,					 x, y, 					 currMV->x, currMV->y, iMinSAD, &newMV, 					 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);		if (iSAD < iMinSAD) 	{		*currMV = newMV;		iMinSAD = iSAD;	}	if (MotionFlags & PMV_EXTSEARCH8)	{/* extended: search (up to) two more times: orignal prediction and (0,0) */		if (!(MVequal(pmv[0],backupMV)) )		{ 	iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,							  x, y, 							  pmv[0].x, pmv[0].y, iMinSAD, &newMV, 							  pmv, 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 = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,							  x, y, 							  0, 0, iMinSAD, &newMV, 							  pmv, 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.   By performing an optional local half-pixel search, we can refine this result even further.*/	PMVfast8_Terminate_with_Refine:	if (MotionFlags & PMV_HALFPELREFINE8) 		// perform final half-pel step 		iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,						 x, y,						 currMV, iMinSAD, 						 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);PMVfast8_Terminate_without_Refine:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -