www.pudn.com > wm2.5.zip > motion_esti.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2004, Advanced Audio Video Coding Standard, Part II 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
#include  
#include   
#include "global.h" 
#include "motion_esti.h" 
#include "interpred.h" 
#include "rdopt.h" 
//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
#include "IREG.h" 
#endif // _ISOLATED_REGION_ 
 
 // for memset() function 
 
extern const int csiInter_Block_Size[4][2]; 
extern const int csiInter_Subblk_Size[4][2]; 
extern int AffectedByLeftover(int x_pos, int y_pos, int ref); 
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function name  : CalIntegerPixSAD 
+ parameters     :  
+ return		 : returns SAD of a integer pel MV 
+ descriptions   : created  by jhzheng : 2004/02/12 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
int CalIntegerPixSAD( 
					 int ref, 
					 int blkindex, 
                     int subblkindex, 
					 int blksize_x, 
					 int blksize_y, 
					 int cand_x, 
					 int cand_y, 
					 int mcost, 
					 int min_mcost, 
           int y_pos, 
           int x_pos) 
{ 
	int y,x; 
	int ypos,xpos; 
	int yoff,xoff,oriy,orix; 
	xoff = ((blkindex &  1)<<3) + ((subblkindex &  1)<<2); 
	yoff = ((blkindex >> 1)<<3) + ((subblkindex >> 1)<<2); 
 
	for (y=0; yimg_height+(PAD_SIZE<<1)-1); 
		oriy = yoff + y; 
		for (x=0; ximg_width+(PAD_SIZE<<1)-1); 
			orix = xoff + x; 
 
      mcost += absm(pgMbData->org_luma[oriy][orix] -  
        reference_frame[ref][0][ypos][xpos]); 
		} 
		if (mcost >= min_mcost) 
			break; 
	} 
 
	return mcost; 
} 
 
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function name  : CalSubPixSAD 
+ parameters     :  
+ return		 : returns SAD of a fractiona pel MV 
+ descriptions   : created  by jhzheng : 2004/02/12 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
int CalSubPixSAD	( 
					 int ref, 
					 int blkindex, 
					 int blksize_x, 
					 int blksize_y, 
					 int cand_x, 
					 int cand_y, 
					 int mcost, 
					 int min_mcost) 
{ 
	int y,x8,i; 
	int ypos,xpos; 
	int yoff,xoff,oriy,orix; 
	xoff = (blkindex &  1)<<3; 
	yoff = (blkindex >> 1)<<3; 
	for (y=0; yorg_luma[oriy][orix+i] -  
					          pgMbData->Sub_pixel_buffer[ref][ypos][xpos+i*4]); 
			} 
		} 
		if (mcost >= min_mcost) 
		{ 
			break; 
		} 
	} 
	return mcost; 
} 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function name  : FME_Integer_Pel_Block_Motion_Search 
+ parameters     :  
+ return		 : cost of the current block 
+ descriptions   : created  by xyji & jhzheng : 2004/02/12 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
 
int														//  ==> minimum motion cost after search 
FME_Integer_Pel_Block_Motion_Search( 
									int ref, 
									int offx, 
									int off_y, 
									int blkindex,		// <--  block index(0~3)       
									int blktype,		// <--  block type (1-16x16 ... 4-8x8) 
									int subblkindex, 
									int subblktype, 
									int min_mcost,		// <--  minimum motion cost (cost for center or huge value) 
									int lambda_factor,   // <--  factor for determining lagragian motion cost 
									int ypos, 
									int xpos 
									) 
{ 
	int   pos,  mcost; 
	int   best_x, best_y, cand_x, cand_y; 
	int   search_step, iYMinNow, iXMinNow; 
	int   i,m;  
	int   iAbort; 
 
	int blksize_y; 
	int blksize_x; 
 
	if(blktype == 4) 
	{ 
		blksize_y   = (csiInter_Subblk_Size[subblktype - 1][1]);  // vertical   block size 
		blksize_x   = (csiInter_Subblk_Size[subblktype - 1][0]);  // horizontal block size 
	} 
	else 
	{ 
		blksize_y   = (csiInter_Block_Size[blktype - 1][1]);  // vertical   block size 
		blksize_x   = (csiInter_Block_Size[blktype - 1][0]);  // horizontal block size 
	} 
 
	for(i = 0 ; i < RANGE_FULL ; i ++) 
	{ 
		memset(pgMbData->Diamond_status[i],0,RANGE_FULL*sizeof(pgMbData->Diamond_status[0][0])); 
	} 
 
	////////////search around the predictor 
	 
	//check the center median predictor 
	cand_x = offx; 
	cand_y = off_y; 
	mcost  = MV_COST(lambda_factor, ((cand_x << 2) - sResidual_MV[0]),  
									((cand_y << 2) - sResidual_MV[1]));   
	mcost  = CalIntegerPixSAD(ref, blkindex,subblkindex,blksize_x,blksize_y, 
									      cand_x,   cand_y,mcost,min_mcost, ypos, xpos); 
 
	pgMbData->Diamond_status[cand_x+SEARCHRANGE][cand_y+SEARCHRANGE] = 1; 
	if (mcost < min_mcost) 
	{ 
		min_mcost = mcost; 
		best_x = cand_x; 
		best_y = cand_y; 
	} 
 
	iXMinNow = best_x;		iYMinNow = best_y; 
	for (m = 0; m < 4; m++) 
	{		 
		cand_x = iXMinNow + pgMbData->Diamond_index[m][0]; 
		cand_y = iYMinNow + pgMbData->Diamond_index[m][1];    
		SEARCH_ONE_PIXEL 
	}  
 
	//current position check 
	//if (((offx - sInter_Pred_MV[blkindex][0]/4)!=0)||((off_y - sInter_Pred_MV[blkindex][1]/4)!=0)) 
	if (((offx - sInteger_MV[0])!=0)||((off_y - sInteger_MV[1])!=0)) 
	{ 
		cand_x = offx  - sInteger_MV[0]; 
		cand_y = off_y - sInteger_MV[1]; 
		SEARCH_ONE_PIXEL 
 
		iXMinNow = best_x;		iYMinNow = best_y; 
		for (m = 0; m < 4; m++) 
		{		 
			cand_x = iXMinNow + pgMbData->Diamond_index[m][0]; 
			cand_y = iYMinNow + pgMbData->Diamond_index[m][1];    
			SEARCH_ONE_PIXEL 
		} 	 
	} 
	 
	//strengthen local search 
	iXMinNow = best_x;		iYMinNow = best_y; 
	for (m = 0; m < 4; m++) 
	{		 
		cand_x = iXMinNow + pgMbData->Diamond_index[m][0]; 
		cand_y = iYMinNow + pgMbData->Diamond_index[m][1];    
		SEARCH_ONE_PIXEL 
	}  
	 
//Unsymmetrical-cross search 	 
//first_step:  
	iXMinNow = best_x;		iYMinNow = best_y; 
	for(i=1;i<=SEARCHRANGE>>1;i++) 
	{ 
		search_step = (i<<1) - 1; 
		cand_x = iXMinNow + search_step; 
		cand_y = iYMinNow ; 
		SEARCH_ONE_PIXEL		 
		cand_x = iXMinNow - search_step; 
		cand_y = iYMinNow ; 
		SEARCH_ONE_PIXEL 
	} 
	 
	for(i=1;i<=SEARCHRANGE>>2;i++) 
	{ 
		search_step = (i<<1) - 1; 
		cand_x = iXMinNow ; 
		cand_y = iYMinNow + search_step; 
		SEARCH_ONE_PIXEL 
		cand_x = iXMinNow ; 
		cand_y = iYMinNow - search_step; 
		SEARCH_ONE_PIXEL 
	} 
	 
	// Uneven Multi-Hexagon-grid Search	 
	iXMinNow = best_x;		iYMinNow = best_y; 
	for(pos=1;pos<25;pos++) 
	{ 
		cand_x = iXMinNow + pgMbData->Spiral_index[pos][0]; 
		cand_y = iYMinNow + pgMbData->Spiral_index[pos][1]; 
		SEARCH_ONE_PIXEL 
	} 
	 
	for(i=1;i<=SEARCHRANGE>>2; i++) 
	{ 
		//iAbort = 0;    
		for (m = 0; m < 16; m++) 
		{ 
			cand_x = iXMinNow + pgMbData->BigHexagon_index[m][0]*i; 
			cand_y = iYMinNow + pgMbData->BigHexagon_index[m][1]*i;  
			//SEARCH_ONE_PIXEL1(1) 
			SEARCH_ONE_PIXEL 
		} 
	} 
	 
//Extended Hexagon-based Search 
//sec_step:   
	iXMinNow = best_x;		iYMinNow = best_y; 
	for(i=0;iHexagon_index[m][0]; 
		  cand_y = iYMinNow + pgMbData->Hexagon_index[m][1];    
		  SEARCH_ONE_PIXEL1(0) 
	  }  
	  if(iAbort) 
		  break; 
	  iXMinNow = best_x;	   
	  iYMinNow = best_y; 
	} 
	 
// the third step with a small search pattern 
//third_step:  
	iXMinNow = best_x;		iYMinNow = best_y; 
	for(i=0;iDiamond_index[m][0]; 
		  cand_y = iYMinNow + pgMbData->Diamond_index[m][1];    
		  SEARCH_ONE_PIXEL1(0) 
	  }  
	  if(iAbort) 
		  break; 
	  iXMinNow = best_x;	   
	  iYMinNow = best_y; 
	} 
 
	// best pos in integer search 
	sInter_MV[blkindex][subblkindex][0] = best_x<<2;		   //qwang 2004-3-21  sInter_MV[blkindex][0] 
	sInter_MV[blkindex][subblkindex][1] = best_y<<2;       //qwang 2004-3-21  sInter_MV[blkindex][1] 
	 
	return min_mcost; 
 
} 
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function name  : FME_Sub_Pel_Block_Motion_Search 
+ parameters     :  
+ return		 : cost of the current block 
+ descriptions   : created  by xyji & jhzheng : 2004/02/12 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
 
int													//  ==> minimum motion cost after search 
FME_Sub_Pel_Block_Motion_Search( 
								int ref, 
								int xoff, 
								int yoff,								 
								int blkindex,		// <--  block index(0~3)       
								int subblkindex, 
								int subblktype,		// <--  block type (1-16x16 ... 4-8x8) 
								int min_mcost,		// <--  minimum motion cost (cost for center or huge value) 
								int lambda_factor,   // <--  factor for determining lagragian motion cost 
								int ypos, 
							    int xpos 
							   )  
{ 
	int   mcost; 
 
	int   blksize_y   = (csiInter_Subblk_Size[subblktype - 1][1]);  // vertical   block size 
    int   blksize_x   = (csiInter_Subblk_Size[subblktype - 1][0]);  // horizontal block size 
 
	int   iXMinNow,iYMinNow,i; 
	int   cand_mv_x, cand_mv_y; 
	int   m,currmv_x,currmv_y; 
	int   abort_search; 
	int   full_x,full_y,sub_x,sub_y; 
	int   pred_frac_x,pred_frac_y;	 
	int   refy, refx; 
	int   y0, oriy,  orix, x0; 
	int   y_pos, x_pos; 
	int   j, diff[16]; 
	int width4  = (pgImage->img_width  + (PAD_SIZE<<1) - 1)<<2; 
  int height4 = (pgImage->img_height + (PAD_SIZE<<1) - 1)<<2; 
 
	for(i = 0 ; i < RANGE_SUB ; i ++) 
	{ 
		memset(pgMbData->Diamond_status[i],0,RANGE_SUB*sizeof(pgMbData->Diamond_status[0][0])); 
	} 
	 
	cand_mv_x = currmv_x = 0; 
	cand_mv_y = currmv_y = 0; 
	pgMbData->Diamond_status[cand_mv_y + SUBSEARANGE][cand_mv_x + SUBSEARANGE] = 1; 
 
	full_x = sInter_MV[blkindex][0][0];				//best pos for Integer search   //qwang 2004-3-21  sInter_MV[blkindex][0] 
	full_y = sInter_MV[blkindex][0][1];	                                      //qwang 2004-3-21  sInter_MV[blkindex][1] 
 
	pred_frac_x = (sResidual_MV[0] - full_x) % 4 ;//&0x03;			//coordinate in sub pixel area 
	pred_frac_y = (sResidual_MV[1] - full_y) % 4 ;//&0x03;  
 
	//search prediction pos in sub pixel area 
	if(pred_frac_x!=0 || pred_frac_y!=0) 
	{ 
		cand_mv_x = pred_frac_x;     
		cand_mv_y = pred_frac_y;     
		if(absm(cand_mv_x) <= SUBSEARANGE && absm(cand_mv_y) <= SUBSEARANGE) 
		{ 
			mcost = MV_COST (lambda_factor, full_x + pred_frac_x - sResidual_MV[0],  
											  full_y + pred_frac_y - sResidual_MV[1]);		 
			 
			//----- add up SAD ---- 
			if(!input.hadamard) 
			{ 
				for (y0 = 0; y0 < blksize_y; y0++) 
				{       
					oriy = yoff + y0; 
					refy = HALF_CENTER_OFFSET + (y0 << 2) + cand_mv_y; 
					 
					for (x0 = 0; x0 < blksize_x; x0++) 
					{ 
						orix = xoff + x0; 
						refx = HALF_CENTER_OFFSET + (x0 << 2) + cand_mv_x; 
						 
						y_pos = ypos+ HALF_CENTER_OFFSET+(y0 << 2)  + cand_mv_y + (PAD_SIZE<<2); 
						x_pos = xpos+ HALF_CENTER_OFFSET+(x0 << 2)  + cand_mv_x + (PAD_SIZE<<2); 
						 
						x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
						y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
						 
						mcost += absm(pgMbData->org_luma[oriy][orix] -  
							reference_quater_pel_frame[ref][y_pos][x_pos]); 
					} 
				} 
			}else 
			{ 
				 
				for (y0 = 0; y0 < blksize_y; y0+=4) 
				{       
					oriy = yoff + y0; 
					refy = HALF_CENTER_OFFSET + (y0 << 2) + cand_mv_y; 
					 
					for (x0 = 0; x0 < blksize_x; x0+=4) 
					{ 
						orix = xoff + x0; 
						refx = HALF_CENTER_OFFSET + (x0 << 2) + cand_mv_x; 
						 
						for(j=0; j<4;j++) 
							for(i=0; i<4;i++)    
							{ 
								y_pos = ypos+ HALF_CENTER_OFFSET+(y0 << 2) + (j<<2) + cand_mv_y + (PAD_SIZE<<2); 
								x_pos = xpos+ HALF_CENTER_OFFSET+(x0 << 2) + (i<<2) + cand_mv_x + (PAD_SIZE<<2); 
								 
								x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
								y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
								 
								diff[j*4+i] = pgMbData->org_luma[oriy+j][orix+i] -  
									reference_quater_pel_frame[ref][y_pos][x_pos];  
							} 
							 
							mcost += SATD(diff); 
					} 
				} 
			} 
 
			pgMbData->Diamond_status[cand_mv_y + SUBSEARANGE][cand_mv_x + SUBSEARANGE] = 1; 
			if (mcost < min_mcost) 
			{ 
				min_mcost = mcost; 
				currmv_x = cand_mv_x; 
				currmv_y = cand_mv_y;	 
			} 
		} 
	} 
 
	iXMinNow = currmv_x; 
	iYMinNow = currmv_y; 
	for(i = 0 ; i < RANGE_SUB ; i ++)  
	{ 
		abort_search=1; 
		for (m = 0; m < 4; m++) 
		{ 
			cand_mv_x = iXMinNow + (pgMbData->Diamond_index[m][0]);//<<2); 
			cand_mv_y = iYMinNow + (pgMbData->Diamond_index[m][1]);//<<2); 
			 
			if(absm(cand_mv_x) <= SUBSEARANGE && absm(cand_mv_y) <= SUBSEARANGE) 
			{ 
				if(!pgMbData->Diamond_status[cand_mv_y + SUBSEARANGE][cand_mv_x + SUBSEARANGE]) 
				{ 
					sub_x = full_x + cand_mv_x;     
					sub_y = full_y + cand_mv_y;  
	 
					mcost = MV_COST (lambda_factor, sub_x - sResidual_MV[0],  
													  sub_y - sResidual_MV[1]);		 
 
								//----- add up SAD ---- 
					if(!input.hadamard) 
					{ 
						for (y0 = 0; y0 < blksize_y; y0++) 
						{       
							oriy = yoff + y0; 
							refy = HALF_CENTER_OFFSET + (y0 << 2) + cand_mv_y; 
							 
							for (x0 = 0; x0 < blksize_x; x0++) 
							{ 
								orix = xoff + x0; 
								refx = HALF_CENTER_OFFSET + (x0 << 2) + cand_mv_x; 
								 
								y_pos = ypos+ HALF_CENTER_OFFSET+(y0 << 2)  + cand_mv_y + (PAD_SIZE<<2); 
								x_pos = xpos+ HALF_CENTER_OFFSET+(x0 << 2)  + cand_mv_x + (PAD_SIZE<<2); 
								 
								x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
								y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
								 
								mcost += absm(pgMbData->org_luma[oriy][orix] -  
									reference_quater_pel_frame[ref][y_pos][x_pos]); 
							} 
						} 
					}else 
					{ 
						 
						for (y0 = 0; y0 < blksize_y; y0+=4) 
						{       
							oriy = yoff + y0; 
							refy = HALF_CENTER_OFFSET + (y0 << 2) + cand_mv_y; 
							 
							for (x0 = 0; x0 < blksize_x; x0+=4) 
							{ 
								orix = xoff + x0; 
								refx = HALF_CENTER_OFFSET + (x0 << 2) + cand_mv_x; 
								 
								for(j=0; j<4;j++) 
									for(i=0; i<4;i++)    
									{ 
										y_pos = ypos+ HALF_CENTER_OFFSET+(y0 << 2) + (j<<2) + cand_mv_y + (PAD_SIZE<<2); 
										x_pos = xpos+ HALF_CENTER_OFFSET+(x0 << 2) + (i<<2) + cand_mv_x + (PAD_SIZE<<2); 
										 
										x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
										y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
										 
										diff[j*4+i] = pgMbData->org_luma[oriy+j][orix+i] -  
											reference_quater_pel_frame[ref][y_pos][x_pos];  
									} 
									 
									mcost += SATD(diff); 
							} 
						} 
					} 
					 
					pgMbData->Diamond_status[cand_mv_y + SUBSEARANGE][cand_mv_x + SUBSEARANGE] = 1; 
					if (mcost < min_mcost) 
					{ 
						min_mcost = mcost; 
						currmv_x = cand_mv_x; 
						currmv_y = cand_mv_y;	 
						abort_search = 0;					 
					} 
				} 
			} 
		} 
		iXMinNow = currmv_x; 
		iYMinNow = currmv_y; 
		if(abort_search) 
			break; 
	} 
	 
	sInter_MV[blkindex][subblkindex][0] += currmv_x;		//qwang 2004-3-21   sInter_MV[blkindex][0] 
	sInter_MV[blkindex][subblkindex][1] += currmv_y;    //qwang 2004-3-21   sInter_MV[blkindex][1] 
	 
	//===== return minimum motion cost ===== 
	return min_mcost; 
} 
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function name  : Sub_Pel_Block_Motion_Search 
+ parameters     : void 
+ return     	 : cost of the current block 
+ descriptions   : created  by xyji & jhzheng: 2004/02/12 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
int											   //  ==> minimum motion cost after search    //qwang 2004-3-24 
Sub_Pel_Block_Motion_Search ( 
							 int ref, 
							 int offx, 
							 int off_y, 
							 int blkindex,    
							 int blktype,      // <--  block type (1-16x16 ... 4-8x8) 
							 int subblkindex,   
							 int subblktype,  
							 int min_mcost,    // <--  minimum motion cost (cost for center or huge value) 
							 int lambda_factor, // <--  factor for determining lagragian motion cost 
							 int ypos, 
							 int xpos 
							 ) 
{ 
	int   pos, best_pos, mcost; 
	int   y0, x0; 
	int   cand_mv_x, cand_mv_y; 
 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    int   Flag_IREG=0; 
    int   xpos_plusoffset = xpos + QUARTER_CENTER_OFFSET; 
    int   ypos_plusoffset = ypos + QUARTER_CENTER_OFFSET; 
#endif // _ISOLATED_REGION_ 
	 
	int   blksize_y;  // vertical   block size 
	int   blksize_x;  // horizontal block size 
	int   i, j; 
	int   quart_startpoint[2] ; 
	int   xoff,yoff,orix,oriy,refx,refy; 
	int   diff[16]; 
  int   y_pos, x_pos; 
  int width4  = (pgImage->img_width  + (PAD_SIZE<<1) - 1)<<2; 
  int height4 = (pgImage->img_height + (PAD_SIZE<<1) - 1)<<2; 
   
	xoff = ((blkindex &  1)<<3) + ((subblkindex &  1)<<2); 
	yoff = ((blkindex >> 1)<<3) + ((subblkindex >> 1)<<2); 
 
  if(blktype == 4) 
  { 
    blksize_y   = (csiInter_Subblk_Size[subblktype - 1][1]);  // vertical   block size 
    blksize_x   = (csiInter_Subblk_Size[subblktype - 1][0]);  // horizontal block size 
  } 
  else 
  { 
    blksize_y   = (csiInter_Block_Size[blktype - 1][1]);  // vertical   block size 
    blksize_x   = (csiInter_Block_Size[blktype - 1][0]);  // horizontal block size 
  } 
 
	quart_startpoint[0] = 0; 
	quart_startpoint[1] = 0; 
 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
        { 
            iSubPixFlag  = 0; 
            iSubPixFlag1 = 0; 
        } 
        else 
        { 
                iSubPixFlag  = 1; 
                iSubPixFlag1 = 0; 
        } 
    } 
#endif // _ISOLATED_REGION_ 
 
	/********************************* 
	*****  HALF-PEL REFINEMENT  ***** 
	*********************************/	 
	 
  //===== loop over search positions ===== 
 
  for (best_pos = 0,  pos = input.hadamard ? 0:1; pos < HALF_SEARCH_RANGE; pos++) 
  { 
    cand_mv_x =  (pgMbData->Spiral_index [pos][0] << 1);    // half-pel units 
    cand_mv_y =  (pgMbData->Spiral_index [pos][1] << 1);    // half-pel units 
 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
        { 
            Flag_IREG = 0; 
            for (y0 = 0; y0 < blksize_y; y0++) 
            {         
                for (x0 = 0; x0 < blksize_x; x0++) 
                { 
                    refx = xpos_plusoffset + ( x0 << 2 ) + cand_mv_x; 
                    refy = ypos_plusoffset + ( y0 << 2 ) + cand_mv_y; 
                    Flag_IREG = AffectedByLeftover(refx, refy, ref); 
                    if ( Flag_IREG ) 
                    { 
                        break; 
                    } 
                     
                } 
                if ( Flag_IREG ) 
                { 
                    break; 
                } 
            } 
            if ( Flag_IREG ) 
            { 
                continue; 
            } 
			if(Flag_IREG==0)iSubPixFlag=1; 
        }// if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
    } 
#endif // _ISOLATED_REGION_ 
     
    //----- set motion vector cost ----- 
    //----- Yulejun 2004.Sep.04 ----- 
    if ( pgImage->half_pixel_mv_flag == 0 ) 
    { 
        mcost = MV_COST (lambda_factor,                                        // for 1/2 pixel ME 
            ( cand_mv_x + sInter_MV[blkindex][subblkindex][0] - sResidual_MV[0] ),           
            ( cand_mv_y + sInter_MV[blkindex][subblkindex][1] - sResidual_MV[1] ) ); 
    } 
    else // 1/2 pixel ME 
    { 
        mcost = MV_COST (lambda_factor,                                        // for 1/2 pixel ME 
            (cand_mv_x) + (sInter_MV[blkindex][subblkindex][0]>>1) - (sResidual_MV[0]>>1),           
            (cand_mv_y) + (sInter_MV[blkindex][subblkindex][1]>>1) - (sResidual_MV[1]>>1) ); 
    } 
    //-------------------------------- 
     
    //----- add up SAD ---- 
    if(!input.hadamard) 
    { 
      for (y0 = 0; y0 < blksize_y; y0++) 
      {       
        oriy = yoff + y0; 
        refy = HALF_CENTER_OFFSET + (y0 << 2) + cand_mv_y; 
    
        for (x0 = 0; x0 < blksize_x; x0++) 
        { 
          orix = xoff + x0; 
          refx = HALF_CENTER_OFFSET + (x0 << 2) + cand_mv_x; 
           
          y_pos = ypos+ HALF_CENTER_OFFSET+(y0 << 2)  + cand_mv_y + (PAD_SIZE<<2); 
          x_pos = xpos+ HALF_CENTER_OFFSET+(x0 << 2)  + cand_mv_x + (PAD_SIZE<<2); 
           
          x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
          y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
           
          mcost += absm(pgMbData->org_luma[oriy][orix] -  
            reference_quater_pel_frame[ref][y_pos][x_pos]); 
        } 
      } 
    }else 
    { 
       
      for (y0 = 0; y0 < blksize_y; y0+=4) 
      {       
        oriy = yoff + y0; 
        refy = HALF_CENTER_OFFSET + (y0 << 2) + cand_mv_y; 
         
        for (x0 = 0; x0 < blksize_x; x0+=4) 
        { 
          orix = xoff + x0; 
          refx = HALF_CENTER_OFFSET + (x0 << 2) + cand_mv_x; 
          
          for(j=0; j<4;j++) 
            for(i=0; i<4;i++)    
            { 
              y_pos = ypos+ HALF_CENTER_OFFSET+(y0 << 2) + (j<<2) + cand_mv_y + (PAD_SIZE<<2); 
              x_pos = xpos+ HALF_CENTER_OFFSET+(x0 << 2) + (i<<2) + cand_mv_x + (PAD_SIZE<<2); 
               
              x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
              y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
    
              diff[j*4+i] = pgMbData->org_luma[oriy+j][orix+i] -  
              reference_quater_pel_frame[ref][y_pos][x_pos];  
            } 
             
            mcost += SATD(diff); 
        } 
      } 
    } 
     
    if (mcost < min_mcost) 
    { 
      min_mcost = mcost; 
      best_pos = pos; 
    } 
  } 
 
  //cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
        { 
            if (iSubPixFlag == 0 && Flag_IREG == 1) 
            { 
                iSubPixFlag1 = 1; 
                return (1 << 30); 
            } 
        } 
    } 
#endif // _ISOLATED_REGION_ 
 
	if (best_pos) 
	{ 
		quart_startpoint[0] = (pgMbData->Spiral_index [best_pos][0] << 1); 
		quart_startpoint[1] = (pgMbData->Spiral_index [best_pos][1] << 1); 
		sInter_MV[blkindex][subblkindex][0] += quart_startpoint[0]; 
		sInter_MV[blkindex][subblkindex][1] += quart_startpoint[1]; 
	} 
	 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
        { 
            iSubPixFlag  = 0; 
            iSubPixFlag1 = 0; 
        } 
        else 
        { 
                iSubPixFlag  = 1; 
                iSubPixFlag1 = 0; 
        } 
    } 
#endif // _ISOLATED_REGION_ 
 
     
    if ( pgImage->half_pixel_mv_flag == 0) // 1/4-pixel MV 
    {  
    /************************************ 
    *****  QUARTER-PEL REFINEMENT  ***** 
        ************************************/ 
         
        //===== loop over search positions ===== 
        for (best_pos = 0, pos = 1; pos < QUARTER_SEARCH_RANGE; pos++) 
        { 
            cand_mv_x = quart_startpoint[0] + pgMbData->Spiral_index [pos][0];    // quarter-pel units 
            cand_mv_y = quart_startpoint[1] + pgMbData->Spiral_index [pos][1];    // quarter-pel units 
             
			//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
            if (input.IREGEnable) 
            { 
                if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
                { 
                    Flag_IREG = 0; 
                    for (y0 = 0; y0 < blksize_y; y0++) 
                    {         
                        for (x0 = 0; x0 < blksize_x; x0++) 
                        { 
                            refx = xpos_plusoffset + ( x0 << 2 ) + cand_mv_x; 
                            refy = ypos_plusoffset + ( y0 << 2 ) + cand_mv_y; 
                            Flag_IREG = AffectedByLeftover(refx, refy, ref); 
                            if ( Flag_IREG ) 
                            { 
                                break; 
                            } 
                             
                        } 
                        if ( Flag_IREG ) 
                        { 
                            break; 
                        } 
                    } 
                    if ( Flag_IREG ) 
                    { 
                        continue; 
                    } 
					if(Flag_IREG==0)iSubPixFlag=1; 
                }//if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
            }//if (input->IREGEnable) 
#endif // _ISOLATED_REGION_ 
			 
            //----- set motion vector cost ----- 
            mcost = MV_COST (lambda_factor,  
			             pgMbData->Spiral_index [pos][0] + sInter_MV[blkindex][0][0] - sResidual_MV[0],  //qwang 2004-3-21  sInter_MV[blkindex][0] 
                         pgMbData->Spiral_index [pos][1] + sInter_MV[blkindex][0][1] - sResidual_MV[1]);       //qwang 2004-3-21  sInter_MV[blkindex][1] 
             
            if(!input.hadamard) 
            { 
                //----- add up SAD ----- 
                for (y0 = 0; y0 < blksize_y; y0++) 
                {       
                    oriy = yoff + y0; 
                    refy = QUARTER_CENTER_OFFSET + (y0<<2) + cand_mv_y; 
                     
                    for (x0 = 0; x0 < blksize_x; x0+=4) 
                    { 
                        orix = xoff + x0; 
                        refx = QUARTER_CENTER_OFFSET + (x0<<2) + cand_mv_x; 
                        for(i = 0 ; i < 4 ; i ++) 
                        { 
                            y_pos = ypos+ QUARTER_CENTER_OFFSET+(y0 << 2) + cand_mv_y + (PAD_SIZE<<2); 
                            x_pos = xpos+ QUARTER_CENTER_OFFSET+(x0 << 2) + (i<<2) + cand_mv_x + (PAD_SIZE<<2); 
                             
                            x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
                            y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
                             
                            mcost += absm(pgMbData->org_luma[oriy][orix + i] -  
                                reference_quater_pel_frame[ref][y_pos][x_pos]); 
                             
                        } 
                    } 
                } 
            }else 
            { 
                for (y0 = 0; y0 < blksize_y; y0+=4) 
                {       
                    oriy = yoff + y0; 
                    refy = QUARTER_CENTER_OFFSET + (y0<<2) + cand_mv_y; 
                     
                    for (x0 = 0; x0 < blksize_x; x0+=4) 
                    { 
                        orix = xoff + x0; 
                        refx = QUARTER_CENTER_OFFSET + (x0<<2) + cand_mv_x; 
                         
                        for(j=0; j<4;j++) 
                            for(i=0; i<4;i++) 
                            { 
                                y_pos = ypos+ QUARTER_CENTER_OFFSET+(y0 << 2) + (j<<2) + cand_mv_y + (PAD_SIZE<<2); 
                                x_pos = xpos+ QUARTER_CENTER_OFFSET+(x0 << 2) + (i<<2) + cand_mv_x + (PAD_SIZE<<2); 
                                 
                                x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4  + (x_pos & 3)) : x_pos; 
                                y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; 
                                 
                                diff[j*4+i] = pgMbData->org_luma[oriy+j][orix+i] -  
                                    reference_quater_pel_frame[ref][y_pos][x_pos];  
                            } 
                             
                            mcost += SATD(diff); 
                    } 
                } 
            } 
            if (mcost < min_mcost) 
            { 
                min_mcost = mcost; 
                best_pos  = pos; 
            } 
        } 
         
		//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
        if (input.IREGEnable) 
        { 
            if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
            { 
                if (iSubPixFlag == 0 && Flag_IREG == 1) 
                { 
                    iSubPixFlag1 = 1; 
                    return (1 << 30); 
                } 
            } 
        } 
#endif // _ISOLATED_REGION_ 
		 
        if (best_pos) 
        { 
            sInter_MV[blkindex][subblkindex][0] += pgMbData->Spiral_index [best_pos][0];        //qwang 2004-3-21  sInter_MV[blkindex][0] 
            sInter_MV[blkindex][subblkindex][1] += pgMbData->Spiral_index [best_pos][1];        //qwang 2004-3-21  sInter_MV[blkindex][1] 
        } 
    } 
 
	//===== return minimum motion cost ===== 
	return min_mcost; 
} 
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function name  : Full_Pel_Block_Motion_Search 
+ parameters     : void 
+ return     	   : cost of the current block 
+ descriptions   : created  by  jhzheng: 2004/02/26 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
int											   //  ==> minimum motion cost after search    // qwang 2004-3-22 
Full_Integer_Pel_Block_Motion_Search ( 
									  int ref, 
									  int offx, 
									  int off_y, 
									  int blkindex,    
									  int blktype,      // <--  block type (1-16x16 ... 4-8x8) 
									  int subblkindex,   
									  int subblktype,    
									  int min_mcost,    // <--  minimum motion cost (cost for center or huge value) 
									  int lambda_factor, // <--  factor for determining lagragian motion cost 
									  int ypos, 
									  int xpos 
									  ) 
{ 
	int pos, cand_x, cand_y, mcost, best_pos; 
	int blksize_y;  // vertical   block size 
	int blksize_x;  // horizontal block size 
 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    int refx, refy; 
    int Flag_IREG=0; 
    int x, y; 
#endif // _ISOLATED_REGION_ 
	 
  if(blktype == 4) 
  { 
    blksize_y   = (csiInter_Subblk_Size[subblktype - 1][1]);  // vertical   block size 
    blksize_x   = (csiInter_Subblk_Size[subblktype - 1][0]);  // horizontal block size 
  } 
  else 
  { 
    blksize_y   = (csiInter_Block_Size[blktype - 1][1]);  // vertical   block size 
    blksize_x   = (csiInter_Block_Size[blktype - 1][0]);  // horizontal block size 
  } 
 
	//int max_pos = SPIRALRANGE; 
  //cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
        { 
            iIntegerPixFlag = 0; 
        } 
		else iIntegerPixFlag=1; 
    } 
#endif // _ISOLATED_REGION_ 
 
	//===== loop over all search positions ===== 
	for (pos = 0; pos < SPIRALRANGE; pos ++) 
	{ 
		//--- set candidate position (absolute position in pel units) --- 
		cand_x = offx  + pgMbData->Spiral_index [pos][0]; 
		cand_y = off_y + pgMbData->Spiral_index [pos][1]; 
 
		//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
        if (input.IREGEnable) 
        { 
            if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
            { 
                Flag_IREG = 0; 
                for (y = 0; y < blksize_y; y++) 
                {               
                    for (x = 0; x < blksize_x; x++) 
                    { 
                        refx = (max(0, min(pgImage->img_width - 1, xpos + x + cand_x))); 
                        refy = (max(0, min(pgImage->img_height - 1, ypos + y + cand_y))); 
                        Flag_IREG = (IREGMap[ref][refy>>4][refx>>4] == 0);//not in iREG , flag=1 
                        if ( Flag_IREG )  
                        { 
                            break; 
                        } 
                    } 
                    if ( Flag_IREG )  
                    { 
                        break; 
                    } 
                } 
                if ( Flag_IREG )  
                { 
                    continue; 
                } 
            } 
			if(Flag_IREG==0)iIntegerPixFlag=1; 
        }//if (input->IREGEnable) 
#endif // _ISOLATED_REGION_ 
		 
        //--- initialize motion cost (cost for motion vector) and check --- 
        if ( pgImage->half_pixel_mv_flag == 0 )  // 1/4-PIXEL ME 
        { 
            mcost = MV_COST (lambda_factor, ((cand_x<<2) - (sResidual_MV[0])),   // for 1/4 pixel ME 
                ((cand_y<<2) - (sResidual_MV[1]))); 
        } 
        else   
        { 
            mcost = MV_COST (lambda_factor, ( (cand_x<<2) - (sResidual_MV[0])) >>1,   // for 1/2 pixel ME 
                ((cand_y<<2) - (sResidual_MV[1])) >> 1); 
        } 
         
		if (blktype == 1 && (cand_x == (offx  - sInteger_MV[0])) && 
							(cand_y == (off_y - sInteger_MV[1]))) 
		{ 
			mcost -= WEIGHTED_COST (lambda_factor, 16); 
		} 
		 
		if (mcost >= min_mcost) 
			continue; 
		 
		mcost  = CalIntegerPixSAD(ref,blkindex,subblkindex,blksize_x,blksize_y, 
											  cand_x,cand_y,mcost,min_mcost, ypos, xpos); 
		 
		//--- check if motion cost is less than minimum cost --- 
		if (mcost < min_mcost) 
		{ 
			best_pos  = pos; 
			min_mcost = mcost; 
		} 
	} 
	 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
		//can't find suitable mv or can't use mv 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
        { 
            if (iIntegerPixFlag == 0) 
            { 
                return 1<<20; 
            } 
        } 
    } 
#endif // _ISOLATED_REGION_ 
	 
	//===== set best motion vector and return minimum motion cost ===== 
	if (best_pos) 
	{ 
		sInter_MV[blkindex][subblkindex][0] = (pgMbData->Spiral_index[best_pos][0] << 2);   //qwang 2004-3-20  sInter_MV[blkindex][0] 
		sInter_MV[blkindex][subblkindex][1] = (pgMbData->Spiral_index[best_pos][1] << 2);   //qwang 2004-3-20  sInter_MV[blkindex][1] 
	} 
	else 
	{ 
		sInter_MV[blkindex][subblkindex][0] = sInter_MV[blkindex][subblkindex][1] = 0;      //qwang 2004-3-20  sInter_MV[blkindex][1] 
	} 
 
	return min_mcost; 
}