www.pudn.com > wm2.5.zip > interprediction.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 "global.h" 
 
 
 
/*! 
************************************************************************ 
* \brief 
*    Set motion vector predictor 
************************************************************************ 
*/ 
void SetMotionVectorPredictor(int  *pmv_x, 
                              int  *pmv_y, 
                              int   ref_frame, 
                              int   block_x, 
                              int   block_y, 
                              int   blockshape_x, 
                              int   blockshape_y, 
                              int   ref) 
{ 
	int mb_x                 = 4*block_x; 
	int mb_y                 = 4*block_y; 
	int pic_block_x          = pgImage->block4_x + block_x; 
	int pic_block_y          = pgImage->block4_y + block_y; 
	int mb_width             = pgImage->width/16; 
 
	//WJP FOR SLICE 
	int mb_available_up =		(pgImage->mb_y == 0) ? 0 : (pgcurrMB->slice_nr == mb_data[pgImage->current_mb_nr-mb_width].slice_nr); 
	int mb_available_left =		(pgImage->mb_x == 0) ? 0 : (pgcurrMB->slice_nr == mb_data[pgImage->current_mb_nr-1].slice_nr); 
	int mb_available_upleft  =	(pgImage->mb_x == 0 || pgImage->mb_y == 0) ? 0 :  
								(pgcurrMB->slice_nr == mb_data[pgImage->current_mb_nr-mb_width-1].slice_nr); 
	int mb_available_upright =	(pgImage->mb_x >= mb_width-1 || pgImage->mb_y == 0) ? 0 :  
								(pgcurrMB->slice_nr == mb_data[pgImage->current_mb_nr-mb_width+1].slice_nr); 
	//WJP END 
	int block_available_up, block_available_left, block_available_upright, block_available_upleft; 
	int mv_a, mv_b, mv_c, mv_d, pred_vec[2]; 
	int mvPredType, rFrameL, rFrameU, rFrameUR; 
	int hv; 
	int ***tmp_mv = pgImage->mv; 
	int a_c, b_c, a_b;//qhg 
	int ABC;//qhg 
	int a[2],b[2],c[2];//qhg 
	 
	/* D B C */ 
	/* A X   */ 
	 
	/* 1 A, B, D are set to 0 if unavailable       */ 
	/* 2 If C is not available it is replaced by D */ 
	block_available_up   = mb_available_up   || (mb_y > 0); 
	block_available_left = mb_available_left || (mb_x > 0); 
	 
	if (mb_y > 0) 
	{ 
		if (mb_x < 8)  // first column of 8x8 blocks 
		{ 
			if (mb_y==8) 
			{ 
				if (blockshape_x == 16)      block_available_upright = 0; 
				else                         block_available_upright = 1; 
			} 
			else 
			{ 
				if (mb_x+blockshape_x != 8)  block_available_upright = 1; 
				else                         block_available_upright = 0; 
			} 
		} 
		else 
		{ 
			if (mb_x+blockshape_x != 16)   block_available_upright = 1; 
			else                           block_available_upright = 0; 
		} 
	} 
	else if (mb_x+blockshape_x != MB_BLOCK_SIZE) 
	{ 
		block_available_upright = block_available_up; 
	} 
	else 
	{ 
		block_available_upright = mb_available_upright; 
	} 
	 
	if (mb_x > 0) 
	{ 
		block_available_upleft = (mb_y > 0 ? 1 : mb_available_up); 
	} 
	else if (mb_y > 0) 
	{ 
		block_available_upleft = mb_available_left; 
	} 
	else 
	{ 
		block_available_upleft = mb_available_upleft; 
	} 
	 
	 
	mvPredType = MVPRED_MEDIAN; 
//	rFrameL    = block_available_left    ? refFrArr[pic_block_y]  [pic_block_x-1             ] : -1; 
	rFrameL    = block_available_left    ? refFrArr[pic_block_y+blockshape_y/4 -1]  [pic_block_x-1] : -1;  //JX 05-4-1 
	rFrameU    = block_available_up      ? refFrArr[pic_block_y-1][pic_block_x]   : -1; 
  //added by MZ 
  
  if(block_available_upright)  
    block_available_upright  = block_available_upright && (refFrArr[pic_block_y-1][pic_block_x+blockshape_x/4]!=-1); 
  if(block_available_upleft) 
    block_available_upleft = block_available_upleft && (refFrArr[pic_block_y-1][pic_block_x-1 ]!=-1); 
  
  
	rFrameUR   = block_available_upright ? refFrArr[pic_block_y-1][pic_block_x+blockshape_x/4] : 
	             block_available_upleft  ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; 
	 
	 
	/* Prediction if only one of the neighbors uses the reference frame 
	* we are checking 
	*/ 
	if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)       mvPredType = MVPRED_L; 
	else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)  mvPredType = MVPRED_U; 
	else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)  mvPredType = MVPRED_UR; 
	// Directional predictions  
	else if(blockshape_x == 8 && blockshape_y == 16) 
	{ 
		if(mb_x == 0) 
 
		{ 
			if(rFrameL == ref_frame) 
				mvPredType = MVPRED_L; 
		} 
		else 
		{ 
			if(rFrameUR == ref_frame) 
				mvPredType = MVPRED_UR; 
		} 
	} 
	else if(blockshape_x == 16 && blockshape_y == 8) 
	{ 
		if(mb_y == 0) 
		{ 
			if(rFrameU == ref_frame) 
				mvPredType = MVPRED_U; 
		} 
		else 
		{ 
			if(rFrameL == ref_frame) 
				mvPredType = MVPRED_L; 
		} 
	} 
//#define MIN(a,b,c) (ab?a>c?a:c:b>c?b:c)//WJP FOR MV prediction 050320 
	a_b=a_c=b_c=0; 
	//printf("%d \n" , pgImage->current_mb_nr); 
	for (hv=0; hv < 2; hv++) 
	{ 
		//mv_a = block_available_left    ? tmp_mv[4+pic_block_x-1             ][pic_block_y  ][hv] : 0; 
		mv_a = block_available_left    ? tmp_mv[4+pic_block_x-1][pic_block_y + (blockshape_y/4) -1 ][hv]: 0; 
		mv_b = block_available_up      ? tmp_mv[4+pic_block_x               ][pic_block_y-1][hv] : 0; 
		mv_d = block_available_upleft  ? tmp_mv[4+pic_block_x-1             ][pic_block_y-1][hv] : 0; 
		mv_c = block_available_upright ? tmp_mv[4+pic_block_x+blockshape_x/4][pic_block_y-1][hv] : mv_d; 
		//qhg 
		a[hv] = mv_a; 
		b[hv] = mv_b; 
		c[hv] = mv_c; 
		a_b+= abs(mv_a-mv_b); 
		a_c+= abs(mv_a-mv_c); 
		b_c+= abs(mv_b-mv_c); 
		 
		switch (mvPredType) 
		{ 
		case MVPRED_MEDIAN: 
/*WJP FOR MV prediction 050320 
			if(!(block_available_upleft || block_available_up || block_available_upright)) 
				pred_vec[hv] = mv_a; 
			else  if(hv==1) 
		  { 
			  ABC = MIN(a_b,a_c,b_c); 
			   
			  if(ABC==a_b) 
			  { 
				  if(ABC==a_c) 
				  { 
					  pred_vec[0] = a[0]; 
					  pred_vec[1] = a[1]; 
				  } 
				  else if(ABC==b_c) 
				  { 
					  pred_vec[0] = b[0]; 
					  pred_vec[1] = b[1]; 
				  } 
				  else 
				  { 
					  pred_vec[0] = (a[0]+b[0]+1)>>1; 
					  pred_vec[1] = (a[1]+b[1]+1)>>1; 
				  } 
			  } 
			  else if(ABC==a_c) 
			  { 
				  if(ABC==b_c) 
				  { 
					  pred_vec[0] = c[0]; 
					  pred_vec[1] = c[1];			 
				  } 
				  else 
				  { 
					  pred_vec[0] = (a[0]+c[0]+1)>>1; 
					  pred_vec[1] = (a[1]+c[1]+1)>>1; 
				  } 
			  } 
			  else 
			  { 
				  pred_vec[0] = (b[0]+c[0]+1)>>1; 
				  pred_vec[1] = (b[1]+c[1]+1)>>1; 
			  } 
		  } 
*/ 
			if(hv == 1) 
			{ 
				ABC = MAX(a_b,a_c,b_c); 
				if(ABC == a_b) 
				{ 
					pred_vec[0] = c[0]; 
					pred_vec[1] = c[1]; 
				} 
				else if(ABC == b_c) 
				{ 
					pred_vec[0] = a[0]; 
					pred_vec[1] = a[1]; 
				} 
				else 
				{ 
					pred_vec[0] = b[0]; 
					pred_vec[1] = b[1]; 
				} 
			} 
			//WJP END	   
			break; 
		case MVPRED_L: 
			pred_vec[hv] = mv_a; 
			break; 
		case MVPRED_U: 
			pred_vec[hv] = mv_b; 
			break; 
		case MVPRED_UR: 
			pred_vec[hv] = mv_c; 
			break; 
		default: 
			break; 
		}  
		 
	} 
 
 
 
    if ( pgImage->half_pixel_mv_flag == 0) 
    { 
        *pmv_x = pred_vec[0]; 
        *pmv_y = pred_vec[1]; 
    } 
    else  
    { 
        *pmv_x =  pred_vec[0] << 1; 
        *pmv_y =  pred_vec[1] << 1; 
    } 
 
} 
 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void FindSkipMVandRef() 
{ 
  int i, j, iii, jjj, pmv[2]; 
	int ***tmp_mv         = pgImage->mv; 
	int mb_available_up   = (pgImage->mb_y == 0)  ? 0 : (pgcurrMB->slice_nr == mb_data[pgImage->current_mb_nr-pgImage->width/16].slice_nr); 
	int mb_available_left = (pgImage->mb_x == 0)  ? 0 : (pgcurrMB->slice_nr == mb_data[pgImage->current_mb_nr-1].slice_nr); 
	int zeroMotionAbove   = !mb_available_up  ? 1 : refFrArr[pgImage->block4_y-1][pgImage->block4_x]  == 0 && tmp_mv[4+pgImage->block4_x  ][pgImage->block4_y-1][0] == 0 && tmp_mv[4+pgImage->block4_x  ][pgImage->block4_y-1][1] == 0 ? 1 : 0; 
//int zeroMotionLeft    = !mb_available_left? 1 : refFrArr[pgImage->block4_y][pgImage->block4_x-1]  == 0 && tmp_mv[4+pgImage->block4_x-1][pgImage->block4_y][0] == 0 && tmp_mv[4+pgImage->block4_x-1][pgImage->block4_y][1] == 0 ? 1 : 0; 
  //MZ 050403 
  int zeroMotionLeft    = !mb_available_left? 1 : refFrArr[pgImage->block4_y+4-1][pgImage->block4_x-1]  == 0 && tmp_mv[4+pgImage->block4_x-1][pgImage->block4_y+4-1][0] == 0 && tmp_mv[4+pgImage->block4_x-1][pgImage->block4_y+4-1][1] == 0 ? 1 : 0; 
	int  img_block_y; 
 
	pgcurrMB->cbp = 0; 
	 
	for (i=0;icof[i][j][iii][jjj]=0; 
	} 
	 
	for (j=4;j<6;j++) 
	{ // reset chroma coeffs 
		  for (i=0;i<4;i++) 
				for (iii=0;iii<4;iii++) 
					for (jjj=0;jjj<4;jjj++) 
						pgImage->cof[i][j][iii][jjj]=0; 
	} 
	 
	 
	img_block_y   = pgImage->block4_y;  
	 
	if (zeroMotionAbove || zeroMotionLeft) 
	{ 
		  for(i=0;i<4;i++) 
				for(j=0;j<4;j++) 
				{ 
					pgImage->mv[pgImage->block4_x+i+BLOCK_SIZE][pgImage->block4_y+j][0] = 0; 
					pgImage->mv[pgImage->block4_x+i+BLOCK_SIZE][pgImage->block4_y+j][1] = 0; 
				} 
	} 
	else 
	{ 
		  SetMotionVectorPredictor (pmv, pmv+1, 0, 0, 0, 16, 16, 0);//Lou 1016 
			for(i=0;i<4;i++) 
				for(j=0;j<4;j++) 
				{ 
					pgImage->mv[pgImage->block4_x+i+BLOCK_SIZE][img_block_y+j][0] = pmv[0]; 
					pgImage->mv[pgImage->block4_x+i+BLOCK_SIZE][img_block_y+j][1] = pmv[1]; 
				} 
	} 
	 
	for (j=0; j<4;j++) 
		  for (i=0; i<4;i++) 
			{ 
				refFrArr[pgImage->block4_y+j][pgImage->block4_x+i] = 0; 
			} 
}