www.pudn.com > avs-m3.rar > block.c


/*! 
 ************************************************************************************* 
 * \file  
 *      block.c 
 * \brief 
 *      block based action such as transform, quantization, re-constructions 
 * 
 * \date: updating  
 *      
 ************************************************************************************* 
 */ 
#include  
#include  
#include "block.h" 
#include "global.h" 
#include "defines.h" 
//#include "compensation.h" 
 
 
  //!< Global Tables for Inverse Quantization 
  const unsigned short IQ_TAB[64] =  
  { 
		32768,36061,38968,42495,46341,50535,55437,60424, 
		32932,35734,38968,42495,46177,50535,55109,59933, 
		65535,35734,38968,42577,46341,50617,55027,60097, 
		32809,35734,38968,42454,46382,50576,55109,60056, 
		65535,35734,38968,42495,46320,50515,55109,60076, 
		65535,35744,38968,42495,46341,50535,55099,60087, 
		65535,35734,38973,42500,46341,50535,55109,60097, 
		32771,35734,38965,42497,46341,50535,55109,60099 
  }; 
 
  const short IQ_SHIFT[64] =  
  { 
	  14,14,14,14,14,14,14,14, 
		13,13,13,13,13,13,13,13, 
		13,12,12,12,12,12,12,12, 
		11,11,11,11,11,11,11,11, 
		11,10,10,10,10,10,10,10, 
		10,9,9,9,9,9,9,9, 
		9,8,8,8,8,8,8,8, 
		7,7,7,7,7,7,7,7 
	}; 
 
  const unsigned char QP_SCALE_CR[64]= 
  { 
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
   10,11,12,13,14,15,16,17,18,19, 
   20,21,22,23,24,25,26,27,28,29, 
   30,31,32,33,34,35,36,37,38,39, 
   40,41,42,42,43,43,44,44,45,45, 
   46,46,47,47,48,48,48,49,49,49, 
   50,50,50,51 
  }; 
 
 
  /*!  
 ************************************************************************************* 
 * \brief : Dequantization of 4x4 block. 
 ************************************************************************************* 
 */ 
void Dequant_B4(int qp, int b8, int b4)     
{ 
  int i, j; 
  int val; 
  int shift, QPI; 
 
  assert((b8 >= 0) && (b8 <= 5)); 
 
  if(b8 >= 4) 
    qp =  QP_SCALE_CR[qp]; 
 
  for (j=0; j<4; j++) 
	  for (i=0; i<4; i++) 
	  { 
      CheckQCoeffValid(pgImage->current_mb_nr,b8,b4,pgcurrMB->pred_residual[b8][b4][j][i]); /* check quantized coefficient */ 
 
		  val  = pgcurrMB->pred_residual[b8][b4][j][i];   //VLD's residual before IQ 
		  shift = IQ_SHIFT[qp]; 
		  QPI   = IQ_TAB[qp];  
		   
		  pgcurrMB->pred_residual[b8][b4][j][i] = (val*QPI+(1<<(shift-1)))>>shift; //IQ coefficients after Dequantization 
 
      CheckDCTCoeffValid(pgImage->current_mb_nr,b8,b4,pgcurrMB->pred_residual[b8][b4][j][i]);  /* Inverse Quantization DCT coefficient Check */       
		   
#if TRACE 
		  if(b8<4) 
			  MB_IQ_Y[((b8>>1)<<3)+((b4>>1)<<2)+j][((b8 &1)<<3)+((b4 &1)<<2)+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
		  else 
			  MB_IQ_UV[b8-4][((b4>>1)<<2)+j][((b4 &1)<<2)+i] = pgcurrMB->pred_residual[b8][b4][j][i];    
#endif 
	  } 
 
} 
 
 /*!  
 ************************************************************************************* 
 * \brief : Inverse transform 4x4 block. 
 ************************************************************************************* 
 */ 
void Inv_Transform_B4(int b8,int b4)     
{ 
  int i, j, i1, j1; 
	int tmp[4]; 
	int tmp_blk[BLOCK_SIZE][BLOCK_SIZE]; 
	 
	//using intermediate array tmp_blk[4][4] as transform unit. 
	//4x4 image data swapping 
	for(j=0; j<4; j++) 
		for(i=0; i<4; i++) 
			tmp_blk[j][i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
		 
	//horizontal transform 
	for (j=0; j<4; j++) 
	{ 
		 
		tmp[0] = (tmp_blk[j][0]+tmp_blk[j][2])<<1;               
		tmp[1] = (tmp_blk[j][0]-tmp_blk[j][2])<<1;                                        
		tmp[3] = (tmp_blk[j][1]*3)+tmp_blk[j][3];        
		tmp[2] = tmp_blk[j][1]-(tmp_blk[j][3]*3);       
		 
		for (i=0; i<2; i++) 
		{ 
			i1=3-i; 
			tmp_blk[j][i] = tmp[i]+tmp[i1]; 
			tmp_blk[j][i1]= tmp[i]-tmp[i1]; 
		} 
	} 
 
	//vertical transform 
	for (i=0; i<4; i++) 
	{ 
		tmp[0] =(tmp_blk[0][i]+tmp_blk[2][i])<<1;               
		tmp[1] =(tmp_blk[0][i]-tmp_blk[2][i])<<1;               
		 
		tmp[3]= (tmp_blk[1][i]*3)+tmp_blk[3][i];        
		tmp[2]= tmp_blk[1][i]- (tmp_blk[3][i]*3);        
		 
		for (j=0; j<2; j++) 
		{ 
			j1=3-j; 
      tmp_blk[j][i] = tmp[j]+tmp[j1]; 
			tmp_blk[j1][i]= tmp[j]-tmp[j1];   // 
       
			//tmp_blk[j][i] =(tmp[j]+tmp[j1]+16)>>5; 
			//tmp_blk[j1][i]=(tmp[j]-tmp[j1]+16)>>5;   // 
		} 
	} 
   
  //added by zhan ma 
  for(j=0; j<4; j++)    
	  for(i=0; i<4; i++) 
    { 
      
       CheckHCoeffValid(pgImage->current_mb_nr,b8,b4,tmp_blk[j][i]);  /* IDCT coefficient check */ 
 
#if TRACE  
		if(b8<4) 
			MB_H_coeff_Y[((b8>>1)<<3)+((b4>>1)<<2)+j][((b8 &1)<<3)+((b4 &1)<<2)+i] = tmp_blk[j][i]; 
		else 
			MB_H_coeff_UV[b8-4][((b4>>1)<<2)+j][((b4 &1)<<2)+i] = tmp_blk[j][i]; 
#endif 
 
     tmp_blk[j][i] = (tmp_blk[j][i] +16)>>5; 
    } 
		 
	//swapping 
	for(j=0; j<4; j++) 
	  for(i=0; i<4; i++) 
		{ 
      pgcurrMB->pred_residual[b8][b4][j][i] = tmp_blk[j][i]; 
	 
		//Just as a intermediate variable for decoding trace 
#if TRACE  
		if(b8<4) 
			MB_IDCT_Y[((b8>>1)<<3)+((b4>>1)<<2)+j][((b8 &1)<<3)+((b4 &1)<<2)+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
		else 
			MB_IDCT_UV[b8-4][((b4>>1)<<2)+j][((b4 &1)<<2)+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
#endif 
		} 
 
} 
 
 /*!  
 ************************************************************************************* 
 * \brief : Reconstruction of a 4x4 block. 
 ************************************************************************************* 
 */ 
void Recon_B4(int b8, int b4)     
{ 
	int i,j; 
	short temp; 
	int blk_off_x, blk_off_y; 
	int Mb_off_x, Mb_off_y; 
	 
	blk_off_x = ((b4 &1)<<2); 
	blk_off_y = ((b4>>1)<<2); 
	Mb_off_x  = ((b8 &1)<<3) + blk_off_x; 
	Mb_off_y  = ((b8>>1)<<3) + blk_off_y; 
	 
  
	for(j=0; j<4; j++) 
	{ 
		for(i=0; i<4; i++) 
		{ 
			if(b8 < 4)   //luma 
			{ 
				 
				temp = (pgcurrMB->pred_sample[b8][b4][i][j] + pgcurrMB->pred_residual[b8][b4][j][i]); 
				pgImage->m7[Mb_off_x+i][Mb_off_y+j] =  pgcurrMB->pred_residual[b8][b4][j][i] = clamp(temp,0,255); 
				imgY[pgImage->pix_y+Mb_off_y+j][pgImage->pix_x+Mb_off_x+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
#if TRACE			 
				MB_Y[Mb_off_y+j][Mb_off_x+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
#endif 
			} 
			else        //chroma 
			{ 
				temp = (pgcurrMB->pred_sample[b8][b4][i][j] + pgcurrMB->pred_residual[b8][b4][j][i] ); 
				pgcurrMB->pred_residual[b8][b4][j][i] = clamp(temp,0,255); 
				imgUV[b8-4][pgImage->pix_c_y+blk_off_y+j][pgImage->pix_c_x+blk_off_x+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
#if TRACE        
				MB_UV[b8-4][blk_off_y+j][blk_off_x+i] = pgcurrMB->pred_residual[b8][b4][j][i]; 
#endif 
				 
			} 
		} 
	} 
} 
 
/*!  
 ************************************************************************************* 
 * \brief :  
 *     Get predition residual. VLD 
 ************************************************************************************* 
 */ 
void Get_residual(int b8,int b4)   
{ 
	int  xx, yy; 
	int  mb_y  = (b8 / 2) << 3; 
	int  mb_x  = (b8 % 2) << 3; 
 
  assert(b8<=5&&b8>=0); 
	 
	if (b8<=3) 
	{ 
		for (yy=0; yypred_residual[b8][b4][yy][xx] = pgImage->m7[mb_x+((b4 &1)<<2)+xx][mb_y+((b4>>1)<<2)+yy];  
	} 
	else 
	{	   
		for (yy=0; yypred_residual[b8][b4][yy][xx] = pgImage->m8[b8-4][((b4 &1)<<2)+xx][((b4>>1)<<2)+yy];  
	} 
} 
 
 
// Notation for comments regarding prediction and predictors. 
// The pels of the 4x4 block are labelled a..p. The predictor pels above 
// are labelled A..H, from the left I..P, and from above left X, as follows: 
// 
//  X A B C D E F G H 
//  I a b c d 
//  J e f g h 
//  K i j k l 
//  L m n o p 
//  M 
//  N 
//  O 
//  P 
// 
 
// Predictor array index definitions 
#define P_X (PredPel[0]) 
#define P_A (PredPel[1]) 
#define P_B (PredPel[2]) 
#define P_C (PredPel[3]) 
#define P_D (PredPel[4]) 
#define P_E (PredPel[5]) 
#define P_F (PredPel[6]) 
#define P_G (PredPel[7]) 
#define P_H (PredPel[8]) 
#define P_I (PredPel[9]) 
#define P_J (PredPel[10]) 
#define P_K (PredPel[11]) 
#define P_L (PredPel[12]) 
#define P_M (PredPel[13]) 
#define P_N (PredPel[14]) 
#define P_O (PredPel[15]) 
#define P_P (PredPel[16]) 
 
/*! 
 *********************************************************************** 
 * \brief 
 *    makes and returns 4x4 blocks with all 5 intra prediction modes 
 * 
 * \return 
 *    DECODING_OK   decoding of intraprediction mode was sucessfull             
 *    SEARCH_SYNC   search next sync element as errors while decoding occured 
 * \notes checke by Zhan MA June 20th 2005 
 *********************************************************************** 
 */ 
int intrapred(int b8,  
              int b4,  
              int ioff,                         //!< pixel offset X within MB 
	            int joff,				//!< pixel offset Y within MB 
	            int img_block_x,			//!< location of block X, multiples of 4 
	            int img_block_y)			//!< location of block Y, multiples of 4 
{ 
  int i,j; 
  int s0; 
  int img_y,img_x; 
  int PredPel[17];  // array of predictor pels 
   
  int block_available_up; 
  int block_available_up_right; 
  int block_available_left; 
  int block_available_left_down; 
  int block_available_up_left; 
  //one 4x4 block one mode 
  byte predmode = pgImage->ipredmode[img_block_x+1][img_block_y+1];   //accordinate based on this 
   
  img_x=img_block_x*4; 
  img_y=img_block_y*4; 
 
 
  block_available_up      = (pgImage->ipredmode[img_block_x+1][img_block_y] >=0);              /// can use frm 
  block_available_left    = (pgImage->ipredmode[img_block_x][img_block_y+1] >=0);            /// can use frm 
  block_available_up_left = (pgImage->ipredmode[img_block_x][img_block_y] >=0); 
  block_available_left_down = 0;  // undecoded 
  block_available_up_right  = 0;  // undecoded 
  
 	// end 
  
  i = (img_x & 15); 
  j = (img_y & 15); 
 
  // form predictor pels 
  if (block_available_up) 
  { 
    P_A = imgY[img_y-1][img_x+0]; 
    P_B = imgY[img_y-1][img_x+1]; 
    P_C = imgY[img_y-1][img_x+2]; 
    P_D = imgY[img_y-1][img_x+3]; 
	  P_E = P_F = P_G = P_H = P_D;   //last 5 pixels is equivalent.  
  } 
  else 
    P_A = P_B = P_C = P_D = P_E = P_F = P_G = P_H = 128; 
  
  // 
  if (block_available_left) 
  { 
    P_I = imgY[img_y+0][img_x-1]; 
    P_J = imgY[img_y+1][img_x-1]; 
    P_K = imgY[img_y+2][img_x-1]; 
    P_L = imgY[img_y+3][img_x-1]; 
	  P_M = P_N = P_O = P_P = P_L; 
  } 
  else 
    P_I = P_J = P_K = P_L = P_M = P_N = P_O = P_P = 128; 
   
  //luma r0 picking up 
  if (block_available_up_left) 
    P_X = imgY[img_y-1][img_x-1]; 
  else 
    P_X = 128; 
 
  //predmode selection   
  // 9 modes proposed by HUST in AVS_Mxxxx 
  switch (predmode) 
  { 
    case DC_PRED:                         // DC prediction  
      s0 = 0; 
      if (block_available_up && block_available_left) 
      {    
        // no edge 
        s0 = (P_A + P_B + P_C + P_D + P_I + P_J + P_K + P_L + 4)/(2*BLOCK_SIZE); 
      } 
      else if (!block_available_up && block_available_left) 
      { 
        // upper edge 
        s0 = (P_I + P_J + P_K + P_L + 2)/BLOCK_SIZE;              
      } 
      else if (block_available_up && !block_available_left) 
      { 
        // left edge 
        s0 = (P_A + P_B + P_C + P_D + 2)/BLOCK_SIZE;              
      } 
      else //if (!block_available_up && !block_available_left) 
      { 
        // top left corner, nothing to predict from 
        s0 = 128;                            
      } 
     
      for (j=0; j < BLOCK_SIZE; j++) 
	  	 for (i=0; i < BLOCK_SIZE; i++) 
        pgcurrMB->pred_sample[b8][b4][i][j] = s0;  // store DC prediction 
    break; 
         
    case VERT_PRED:                       // vertical prediction from block above  
      for(j=0;jpred_sample[b8][b4][i][j]=imgY[img_y-1][img_x+i];// store predicted 4x4 block  
    break; 
       
    case HOR_PRED:                        // horisontal prediction from left block  
      for(j=0;jpred_sample[b8][b4][i][j]=imgY[img_y+j][img_x-1]; // store predicted 4x4 block  
    break; 
       
    case DOWN_RIGHT_PRED: 
      pgcurrMB->pred_sample[b8][b4][0][3] = (P_L + 2*P_K + P_J + 2) / 4;  
      pgcurrMB->pred_sample[b8][b4][0][2] = 
      pgcurrMB->pred_sample[b8][b4][1][3] = (P_K + 2*P_J + P_I + 2) / 4;  
      pgcurrMB->pred_sample[b8][b4][0][1] = 
      pgcurrMB->pred_sample[b8][b4][1][2] =  
      pgcurrMB->pred_sample[b8][b4][2][3] = (P_J + 2*P_I + P_X + 2) / 4;  
      pgcurrMB->pred_sample[b8][b4][0][0] = 
      pgcurrMB->pred_sample[b8][b4][1][1] = 
      pgcurrMB->pred_sample[b8][b4][2][2] = 
      pgcurrMB->pred_sample[b8][b4][3][3] = (P_I + 2*P_X + P_A + 2) / 4;  
      pgcurrMB->pred_sample[b8][b4][1][0] = 
      pgcurrMB->pred_sample[b8][b4][2][1] = 
      pgcurrMB->pred_sample[b8][b4][3][2] = (P_X + 2*P_A + P_B + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][2][0] = 
      pgcurrMB->pred_sample[b8][b4][3][1] = (P_A + 2*P_B + P_C + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][3][0] = (P_B + 2*P_C + P_D + 2) / 4; 
    break; 
     
    case DOWN_LEFT_PRED: 
      pgcurrMB->pred_sample[b8][b4][0][0] = (P_A + P_C + P_I + P_K + 2*(P_B + P_J) + 4) / 8; 
      pgcurrMB->pred_sample[b8][b4][1][0] =  
      pgcurrMB->pred_sample[b8][b4][0][1] = (P_B + P_D + P_J + P_L + 2*(P_C + P_K) + 4) / 8; 
      pgcurrMB->pred_sample[b8][b4][2][0] = 
      pgcurrMB->pred_sample[b8][b4][1][1] = 
      pgcurrMB->pred_sample[b8][b4][0][2] = (P_C + P_E + P_K + P_M + 2*(P_D + P_L) + 4) / 8; 
      pgcurrMB->pred_sample[b8][b4][3][0] =  
      pgcurrMB->pred_sample[b8][b4][2][1] =  
      pgcurrMB->pred_sample[b8][b4][1][2] =  
      pgcurrMB->pred_sample[b8][b4][0][3] = (P_D + P_F + P_L + P_N + 2*(P_E + P_M) + 4) / 8; 
      pgcurrMB->pred_sample[b8][b4][3][1] =  
      pgcurrMB->pred_sample[b8][b4][2][2] =  
      pgcurrMB->pred_sample[b8][b4][1][3] = (P_E + P_G + P_M + P_O + 2*(P_F + P_N) + 4) / 8; 
      pgcurrMB->pred_sample[b8][b4][3][2] =  
      pgcurrMB->pred_sample[b8][b4][2][3] = (P_F + P_H + P_N + P_P + 2*(P_G + P_O) + 4) / 8; 
      pgcurrMB->pred_sample[b8][b4][3][3] = (P_G + P_O + P_H + P_P + 2) / 4; 
    break; 
      	 
    case VERT_RIGHT_PRED: // 5 make VERT_RIGHT_PRED Prediction   
      pgcurrMB->pred_sample[b8][b4][0][0] =  
      pgcurrMB->pred_sample[b8][b4][1][2] = (P_X + P_A + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][0] =  
      pgcurrMB->pred_sample[b8][b4][2][2] = (P_A + P_B + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][2][0] =  
      pgcurrMB->pred_sample[b8][b4][3][2] = (P_B + P_C + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][3][0] = (P_C + P_D + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][0][1] =  
      pgcurrMB->pred_sample[b8][b4][1][3] = (P_I + 2*P_X + P_A + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][1][1] =  
      pgcurrMB->pred_sample[b8][b4][2][3] = (P_X + 2*P_A + P_B + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][2][1] =  
      pgcurrMB->pred_sample[b8][b4][3][3] = (P_A + 2*P_B + P_C + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][3][1] = (P_B + 2*P_C + P_D + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][0][2] = (P_X + 2*P_I + P_J + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][0][3] = (P_I + 2*P_J + P_K + 2) / 4; 
    break; 
     
    case HOR_DOWN_PRED: // 6 make HOR_DOWN_PRED Prediction 
      pgcurrMB->pred_sample[b8][b4][0][0] =  
      pgcurrMB->pred_sample[b8][b4][2][1] = (P_X + P_I + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][0] =  
      pgcurrMB->pred_sample[b8][b4][3][1] = (P_I + 2*P_X + P_A + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][2][0] = (P_X + 2*P_A + P_B + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][3][0] = (P_A + 2*P_B + P_C + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][0][1] =  
      pgcurrMB->pred_sample[b8][b4][2][2] = (P_I + P_J + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][1] =  
      pgcurrMB->pred_sample[b8][b4][3][2] = (P_X + 2*P_I + P_J + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][0][2] =  
      pgcurrMB->pred_sample[b8][b4][2][3] = (P_J + P_K + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][2] =  
      pgcurrMB->pred_sample[b8][b4][3][3] = (P_I + 2*P_J + P_K + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][0][3] = (P_K + P_L + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][3] = (P_J + 2*P_K + P_L + 2) / 4; 
 	  break; // end HOR_DOWN_PRED 
     
    case VERT_LEFT_PRED: // 7 make VERT_LEFT_PRED Prediction 
      pgcurrMB->pred_sample[b8][b4][0][0] = (P_A + P_B + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][0] =  
      pgcurrMB->pred_sample[b8][b4][0][2] = (P_B + P_C + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][2][0] =  
      pgcurrMB->pred_sample[b8][b4][1][2] = (P_C + P_D + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][3][0] =  
      pgcurrMB->pred_sample[b8][b4][2][2] = (P_D + P_E + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][3][2] = (P_E + P_F + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][0][1] = (P_A + 2*P_B + P_C + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][1][1] =  
      pgcurrMB->pred_sample[b8][b4][0][3] = (P_B + 2*P_C + P_D + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][2][1] =  
      pgcurrMB->pred_sample[b8][b4][1][3] = (P_C + 2*P_D + P_E + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][3][1] =  
      pgcurrMB->pred_sample[b8][b4][2][3] = (P_D + 2*P_E + P_F + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][3][3] = (P_E + 2*P_F + P_G + 2) / 4; 
    break; // end VERT_LEFT_PRED	 
     
    case HOR_UP_PRED: // 7 make HOR_UP_PRED Prediction 
      pgcurrMB->pred_sample[b8][b4][0][0] = (P_I + P_J + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][1][0] = (P_I + 2*P_J + P_K + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][2][0] =  
      pgcurrMB->pred_sample[b8][b4][0][1] = (P_J + P_K + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][3][0] =  
      pgcurrMB->pred_sample[b8][b4][1][1] = (P_J + 2*P_K + P_L + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][2][1] =  
      pgcurrMB->pred_sample[b8][b4][0][2] = (P_K + P_L + 1) / 2; 
      pgcurrMB->pred_sample[b8][b4][3][1] =  
      pgcurrMB->pred_sample[b8][b4][1][2] = (P_K + 2*P_L + P_M + 2) / 4; 
      pgcurrMB->pred_sample[b8][b4][0][3] = 
      pgcurrMB->pred_sample[b8][b4][2][2] =  
      pgcurrMB->pred_sample[b8][b4][3][2] =  
      pgcurrMB->pred_sample[b8][b4][1][3] =  
      pgcurrMB->pred_sample[b8][b4][2][3] =  
      pgcurrMB->pred_sample[b8][b4][3][3] = P_L; 
    break; // end HOR_UP_PRED 
        
    default: 
      printf("Error: illegal prediction mode input: %d\n",predmode); 
      return SEARCH_SYNC; 
    break; 
  } 
 
#if TRACE 
  for(j=0;j<4;j++) 
	  for(i=0;i<4;i++) 
     MB_intrapred_Y[((b8>>1)<<3)+((b4>>1)<<2)+j][((b8 &1)<<3)+((b4 &1)<<2)+i] = pgcurrMB->pred_sample[b8][b4][i][j]; 
#endif 
  return DECODING_OK; 
} 
 
/*! 
************************************************************************* 
* \brief: 
*    intra chroma prediction based on 4x4 block 
************************************************************************* 
*/ 
void intrapred_chroma_4x4(int mb_x, int mb_y, int b4, int mode) 
{ 
#define CBS 4 // chroma block size 
  unsigned char edgepixu[20]; 
#define EU (edgepixu + 10) 
  unsigned char edgepixv[20]; 
#define EV (edgepixv + 10) 
  int hlineU[CBS],vlineU[CBS]; 
  int hlineV[CBS],vlineV[CBS]; 
  int x,y; 
  int uv;  
  int u0,v0; 
  int bx = (b4 &1)<<2; 
  int by = (b4>>1)<<2; 
  int img_cx = (mb_x << 3) + bx;    // block pel x 
  int img_cy = (mb_y << 3) + by;    // block pel y 
  //MZ 
   
  int mb_available_up      = (pgImage->ipredmode[(mb_x<<2)+1][(mb_y<<2)]>=0); 
  int mb_available_left    = (pgImage->ipredmode[(mb_x<<2)][(mb_y<<2)+1] >=0);            /// can use frm 
  int mb_available_up_left = (pgImage->ipredmode[(mb_x<<2)][(mb_y<<2)] >=0); 
  // 
  int block_available_up      = (b4 ==0||b4==1)?mb_available_up:1; 
  int block_available_left    = (b4 ==0||b4==2)?mb_available_left:1; 
  int block_available_up_left = (b4==0) ? mb_available_up_left : ((b4==1) ? mb_available_up : ((b4==2) ? mb_available_left : 1 )); 
      
  assert(b4>=0 && b4 <=3); 
  uv = 0; 
  if (block_available_up) 
  { 
    for(x=0;xpred_sample[4][b4][x][y] = u0; 
          pgcurrMB->pred_sample[5][b4][x][y] = v0;   
        } 
      } 
 
    break; 
     
    case HOR_PRED_8: 
      if (!block_available_left) 
          error("unexpected HOR_PRED_8 chroma intra prediction mode",-1); 
      for (y=0;ypred_sample[4][b4][x][y] = vlineU[y]; 
          pgcurrMB->pred_sample[5][b4][x][y] = vlineV[y]; 
        } 
      } 
    break; 
     
    case VERT_PRED_8: 
      if (!block_available_up) 
        error("unexpected VERT_PRED_8 chroma intra prediction mode",-1); 
      for (x=0;xpred_sample[4][b4][x][y] = hlineU[x]; 
          pgcurrMB->pred_sample[5][b4][x][y] = hlineV[x]; 
        } 
      } 
    break; 
 
    default: 
        error("intrapred_chroma_4x4:illegal chroma intra prediction mode", 600); 
        break; 
    } 
 
#if TRACE 
   for(y=0;y>1)<<2)+y][((b4 &1)<<2)+x] = pgcurrMB->pred_sample[4][b4][x][y]; 
       MB_intrapred_UV[1][((b4>>1)<<2)+y][((b4 &1)<<2)+x] = pgcurrMB->pred_sample[5][b4][x][y]; 
     }     
#endif 
} 
 
/*! 
************************************************************************ 
* \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: 
			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; 
		}  
		 
	} 
 
  /* MV predictor */ 
  *pmv_x = pred_vec[0]; 
  *pmv_y = pred_vec[1]; 
} 
 
 
 
/*! 
 *********************************************************************** 
 * \brief 
 *    Find Skip Motion Vector for SKIP_MB 
 *********************************************************************** 
 */ 
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; 
			} 
}