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


  /* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2003, 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. 
************************************************************************ 
*/ 
 
/* 
************************************************************************************* 
* File name: intra.c 
* Function: Process one macroblock 
* 
************************************************************************************* 
*/ 
#include  
#include  
#include  
 
#include "define.h" 
#include "global.h" 
#include "intrapred.h" 
#include "block.h" 
#include "rdopt.h" 
#include "vlc.h" 
#include "ratectl.h" 
 
#define INTRA_VLIW_ZP 1 
#define EP (edgepixels+20) 
#define EPU (edgepixu+20)     //qwang 2004-3-7 
#define EPV (edgepixv+20)     //qwang 2004-3-7 
 
extern const short QP_SCALE_CR[64]; 
extern int cofAC[6][4][2][18];  
 
// 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 
 *    Make intra 4x4 prediction according to all 9 prediction modes. 
 *    The routine uses left and upper neighbouring points from 
 *    previous coded blocks to do this (if available). Notice that 
 *    inaccessible neighbouring points are signalled with a negative 
 *    value in the predmode array . 
 * 
 *  \para Input: 
 *     Starting point of current 4x4 block image posision 
 * 
 *  \para Output: 
 *      none 
 ************************************************************************ 
 */ 
int intrapred_luma(int img_x,int img_y,int intramode) //zhangnan 
{ 
	int i,j; 
	int s0; 
	int PredPel[17];  // array of predictor pels 
	 
  int block_available_up        = (ipredmode[img_x/BLOCK_SIZE+1][img_y/BLOCK_SIZE] >=0); 
	int block_available_left      = (ipredmode[img_x/BLOCK_SIZE][img_y/BLOCK_SIZE+1] >=0); 
  int block_available_up_left   = (ipredmode[img_x/BLOCK_SIZE][img_y/BLOCK_SIZE] >=0); 
 
	int block_available_up_right  = 0;  
  int block_available_left_down = 0;  
// end 
 
  int b4_x, b4_y; 
 
  b4_x=img_x>>2; 
  b4_y=img_y>>2; 
 
  i = (img_x & 15); 
  j = (img_y & 15); 
 
  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; 
  } 
  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; 
   
  //getting luma r0's value 
  if (block_available_up_left) 
  	P_X = imgY[img_y-1][img_x-1]; 
  else 
	  P_X = 128; 
  
 
switch (intramode) 
  {  
	 // make DC prediction : the same as h.264 
   case DC_PRED: 
	  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) 
	  { 
		  // left edge 
		  s0 = (P_I + P_J + P_K + P_L + 2)/BLOCK_SIZE;              
	  } 
	  else if (block_available_up && !block_available_left) 
	  { 
		  // upper 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++) 
		 	  pgMbData->pred_curr[0][i][j] = s0;// store DC prediction 
		   
  break; 
 
   
  /////////////////////////////// 
  // make horiz and vert prediction 
  /////////////////////////////// 
 case VERT_PRED: 
  if(block_available_up) 
   for(j=0;jpred_curr[0][j][i]=imgY[img_y-1][img_x+i];// store predicted 4x4 block  
   else 
		return 0; 
  break; 
 
 case HOR_PRED: 
	if (block_available_left) 
		for(j=0;jpred_curr[0][j][i]=imgY[img_y+j][img_x-1]; // store predicted 4x4 block  
 
    else 
		return 0; 
	break; 
 
  /*  Prediction according to 'diagonal' modes */ 
 case DOWN_RIGHT_PRED: 
  if (block_available_up && block_available_left) 
  { 
    // Mode DOWN_RIGHT_PRED 
    pgMbData->pred_curr[0][3][0] = (P_L + 2*P_K + P_J + 2) / 4;  
    pgMbData->pred_curr[0][2][0] = 
    pgMbData->pred_curr[0][3][1] = (P_K + 2*P_J + P_I + 2) / 4;  
    pgMbData->pred_curr[0][1][0] = 
    pgMbData->pred_curr[0][2][1] =  
    pgMbData->pred_curr[0][3][2] = (P_J + 2*P_I + P_X + 2) / 4;  
    pgMbData->pred_curr[0][0][0] = 
    pgMbData->pred_curr[0][1][1] = 
    pgMbData->pred_curr[0][2][2] = 
    pgMbData->pred_curr[0][3][3] = (P_I + 2*P_X + P_A + 2) / 4;  
    pgMbData->pred_curr[0][0][1] = 
    pgMbData->pred_curr[0][1][2] = 
    pgMbData->pred_curr[0][2][3] = (P_X + 2*P_A + P_B + 2) / 4; 
    pgMbData->pred_curr[0][0][2] = 
    pgMbData->pred_curr[0][1][3] = (P_A + 2*P_B + P_C + 2) / 4; 
    pgMbData->pred_curr[0][0][3] = (P_B + 2*P_C + P_D + 2) / 4; 
  } 
	else 
		return 0; 
     break; 
 
    // Mode DOWN_LEFT_PRED 
 case DOWN_LEFT_PRED: 
  if(block_available_left&&block_available_up) 
  { 
	pgMbData->pred_curr[0][0][0] = (P_A + P_C + P_I + P_K + 2*(P_B + P_J) + 4) / 8; 
    pgMbData->pred_curr[0][0][1] =  
    pgMbData->pred_curr[0][1][0] = (P_B + P_D + P_J + P_L + 2*(P_C + P_K) + 4) / 8; 
    pgMbData->pred_curr[0][0][2] = 
    pgMbData->pred_curr[0][1][1] = 
    pgMbData->pred_curr[0][2][0] = (P_C + P_E + P_K + P_M + 2*(P_D + P_L) + 4) / 8; 
    pgMbData->pred_curr[0][0][3] =  
    pgMbData->pred_curr[0][1][2] =  
    pgMbData->pred_curr[0][2][1] =  
    pgMbData->pred_curr[0][3][0] = (P_D + P_F + P_L + P_N + 2*(P_E + P_M) + 4) / 8; 
    pgMbData->pred_curr[0][1][3] =  
    pgMbData->pred_curr[0][2][2] =  
    pgMbData->pred_curr[0][3][1] = (P_E + P_G + P_M + P_O + 2*(P_F + P_N) + 4) / 8; 
    pgMbData->pred_curr[0][2][3] =  
    pgMbData->pred_curr[0][3][2] = (P_F + P_H + P_N + P_P + 2*(P_G + P_O) + 4) / 8; 
    pgMbData->pred_curr[0][3][3] = (P_G + P_O + P_H + P_P + 2) / 4; 
  } 
  else 
		return 0; 
	  break; 
/****************  for intra 9 modes by jx  *****************/	 
 
case VERT_RIGHT_PRED: // 5 make VERT_RIGHT_PRED Prediction   
	if(block_available_left && block_available_up ) 
	{ 
		pgMbData->pred_curr[0][0][0] =  
		pgMbData->pred_curr[0][2][1] = (P_X + P_A + 1) / 2; 
		pgMbData->pred_curr[0][0][1] =  
		pgMbData->pred_curr[0][2][2] = (P_A + P_B + 1) / 2; 
		pgMbData->pred_curr[0][0][2] =  
		pgMbData->pred_curr[0][2][3] = (P_B + P_C + 1) / 2; 
		pgMbData->pred_curr[0][0][3] = (P_C + P_D + 1) / 2; 
		pgMbData->pred_curr[0][1][0] =  
		pgMbData->pred_curr[0][3][1] = (P_I + 2*P_X + P_A + 2) / 4; 
		pgMbData->pred_curr[0][1][1] =  
		pgMbData->pred_curr[0][3][2] = (P_X + 2*P_A + P_B + 2) / 4; 
		pgMbData->pred_curr[0][1][2] =  
		pgMbData->pred_curr[0][3][3] = (P_A + 2*P_B + P_C + 2) / 4; 
		pgMbData->pred_curr[0][1][3] = (P_B + 2*P_C + P_D + 2) / 4; 
		pgMbData->pred_curr[0][2][0] = (P_X + 2*P_I + P_J + 2) / 4; 
		pgMbData->pred_curr[0][3][0] = (P_I + 2*P_J + P_K + 2) / 4; 
	} 
	else 
		return 0; 
	break; // end VERT_RIGHT_PRED 
	 
case HOR_DOWN_PRED: // 6 make HOR_DOWN_PRED Prediction 
	if(block_available_left && block_available_up) 
	{ 
		pgMbData->pred_curr[0][0][0] =  
		pgMbData->pred_curr[0][1][2] = (P_X + P_I + 1) / 2; 
		pgMbData->pred_curr[0][0][1] =  
		pgMbData->pred_curr[0][1][3] = (P_I + 2*P_X + P_A + 2) / 4; 
		pgMbData->pred_curr[0][0][2] = (P_X + 2*P_A + P_B + 2) / 4; 
		pgMbData->pred_curr[0][0][3] = (P_A + 2*P_B + P_C + 2) / 4; 
		pgMbData->pred_curr[0][1][0] =  
		pgMbData->pred_curr[0][2][2] = (P_I + P_J + 1) / 2; 
		pgMbData->pred_curr[0][1][1] =  
		pgMbData->pred_curr[0][2][3] = (P_X + 2*P_I + P_J + 2) / 4; 
		pgMbData->pred_curr[0][2][0] =  
		pgMbData->pred_curr[0][3][2] = (P_J + P_K + 1) / 2; 
		pgMbData->pred_curr[0][2][1] =  
		pgMbData->pred_curr[0][3][3] = (P_I + 2*P_J + P_K + 2) / 4; 
		pgMbData->pred_curr[0][3][0] = (P_K + P_L + 1) / 2; 
		pgMbData->pred_curr[0][3][1] = (P_J + 2*P_K + P_L + 2) / 4; 
	} 
	else 
		return 0; 
	break; // end HOR_DOWN_PRED 
	 
case VERT_LEFT_PRED: // 7 make VERT_LEFT_PRED Prediction 
	if(block_available_up)  //dsk 
	{ 
		pgMbData->pred_curr[0][0][0] = (P_A + P_B + 1) / 2; 
		pgMbData->pred_curr[0][0][1] =  
		pgMbData->pred_curr[0][2][0] = (P_B + P_C + 1) / 2; 
		pgMbData->pred_curr[0][0][2] =  
		pgMbData->pred_curr[0][2][1] = (P_C + P_D + 1) / 2; 
		pgMbData->pred_curr[0][0][3] =  
		pgMbData->pred_curr[0][2][2] = (P_D + P_E + 1) / 2; 
		pgMbData->pred_curr[0][2][3] = (P_E + P_F + 1) / 2; 
		pgMbData->pred_curr[0][1][0] = (P_A + 2*P_B + P_C + 2) / 4; 
		pgMbData->pred_curr[0][1][1] =  
		pgMbData->pred_curr[0][3][0] = (P_B + 2*P_C + P_D + 2) / 4; 
		pgMbData->pred_curr[0][1][2] =  
		pgMbData->pred_curr[0][3][1] = (P_C + 2*P_D + P_E + 2) / 4; 
		pgMbData->pred_curr[0][1][3] =  
		pgMbData->pred_curr[0][3][2] = (P_D + 2*P_E + P_F + 2) / 4; 
		pgMbData->pred_curr[0][3][3] = (P_E + 2*P_F + P_G + 2) / 4; 
	} 
	else 
		return 0; 
	break; // end VERT_LEFT_PRED	 
   
case HOR_UP_PRED: // 8 make HOR_UP_PRED Prediction 
	if(block_available_left) 
	{ 
		pgMbData->pred_curr[0][0][0] = (P_I + P_J + 1) / 2; 
		pgMbData->pred_curr[0][0][1] = (P_I + 2*P_J + P_K + 2) / 4; 
		pgMbData->pred_curr[0][0][2] =  
		pgMbData->pred_curr[0][1][0] = (P_J + P_K + 1) / 2; 
		pgMbData->pred_curr[0][0][3] =  
		pgMbData->pred_curr[0][1][1] = (P_J + 2*P_K + P_L + 2) / 4; 
		pgMbData->pred_curr[0][1][2] =  
		pgMbData->pred_curr[0][2][0] = (P_K + P_L + 1) / 2; 
		pgMbData->pred_curr[0][1][3] =  
		pgMbData->pred_curr[0][2][1] = (P_K + 2*P_L + P_M + 2) / 4; 
		 
		pgMbData->pred_curr[0][3][0] =  
		pgMbData->pred_curr[0][2][2] =  
		pgMbData->pred_curr[0][2][3] =  
		pgMbData->pred_curr[0][3][1] =  
		pgMbData->pred_curr[0][3][2] =  
		pgMbData->pred_curr[0][3][3] = P_L; 
		 
	} 
	else 
		return 0; 
	break; // end HOR_UP_PRED 
/****************************************************/ 
  default: 
	  fprintf(stderr,"Error in intrapred_luma"); 
	  break; 
  } 
  return 1; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Make intra 4x4 prediction according to all 9 prediction modes. 
 *    The routine uses left and upper neighbouring points from 
 *    previous coded blocks to do this (if available). Notice that 
 *    inaccessible neighbouring points are signalled with a negative 
 *    value in the predmode array . 
 * 
 *  \para Input: 
 *     Starting point of current 4x4 block image posision 
 * 
 *  \para Output: 
 *      none 
 ************************************************************************ 
 */ 
int Intra_Luma_Prediction (int * min_cost)   //qwang 2004-3-5 
{ 
  int b8, b4, cost4x4; 
  int dummy; 
 
  //WJP FOR I_DIRECT 
	int i,j; 
	int block_x, block_y; 
	int pic_pix_x; 
	int pic_pix_y; 
	int pic_block_x; 
	int pic_block_y; 
	int dir_abort=0; 
	int intra_cost = 0;	 
	int I_direct_cost = 0; 
	short tmp_cbp,tmp_cbp_4x4[6]; 
	int tmp_ipmode[4][4]; 
	int tmp_cofAC[4][4][2][18]; 
	unsigned char tmp_Y[4][4][4][4]; 
	 
	pgMbHeader->I_MODE = 1/*0 dongjie(check) */; 
	//WJP END 
	 
	//GET THE I4X4 COST 
	for (b8=0; b8<4; b8++)     
	{ 
		for (b4=0; b4<4; b4++) 
		{ 
			Mode_Decision_for_4x4IntraBlocks_luma (b8, b4, &cost4x4, &dummy); 
			intra_cost += cost4x4; 
		} 
		// dongjie 
		if(pgMbHeader->cbp_4x4[b8]==0) 
			pgMbHeader->cbp &= (~(1<cbp |= (1<picture_code_type == INTRA_IMG)  
	{ 
		//save the data for intra4x4 
		tmp_cbp = pgMbHeader->cbp; 
		// dongjie 
		pgMbHeader->cbp = 0; 
		for(i=0;i<6;i++) 
		{ 
			tmp_cbp_4x4[i] = pgMbHeader->cbp_4x4[i]; 
			pgMbHeader->cbp_4x4[i] = 0; 
		} 
		// end		 
		for (b8=0; b8<4; b8++)     
		{ 
			for (b4=0; b4<4; b4++) 
			{ 
				block_x    =(((b8 &1)<<3)+((b4 &1)<<2)); 
				block_y    =(((b8>>1)<<3)+((b4>>1)<<2));			 
				pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); 
				pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); 
				pic_pix_x  = (pic_block_x<<2); 
				pic_pix_y  = (pic_block_y<<2); 
 
				tmp_ipmode[b8][b4] = ipredmode[pic_block_x+1][pic_block_y+1]; 
 
				for(j=0;j<4;j++) 
					for(i=0;i<4;i++) 
						tmp_Y[b8][b4][j][i] = pgMbData->pred_sample[b8][b4][j][i]; 
					 
				for(j=0;j<2;j++) 
					for(i=0;i<18;i++) 
						tmp_cofAC[b8][b4][j][i] = cofAC[b8][b4][j][i]; 
			} 
		} 
 
		//GET THE I_direct COST 
		for (b8=0; b8<4 && dir_abort==0; b8++)     
		{ 
			for (b4=0; b4<4 && dir_abort==0; b4++) 
			{ 
				RD_cost_for_4x4_dir_IntraBlocks_luma (b8, b4, &cost4x4, &dir_abort); 
				I_direct_cost += cost4x4; 
			} 
			// dongjie 
			if(pgMbHeader->cbp_4x4[b8]==0) 
				pgMbHeader->cbp &= (~(1<cbp |= (1<I_MODE = 1/*0 dongjie(check) */; 
			pgMbHeader->cbp = tmp_cbp; 
			// dongjie 
			for(i=0;i<6;i++) 
			{ 
				pgMbHeader->cbp_4x4[i] = tmp_cbp_4x4[i]; 
			} 
			// end 
			for (b8=0; b8<4; b8++)     
			{ 
				for (b4=0; b4<4; b4++) 
				{ 
					block_x    =(((b8 &1)<<3)+((b4 &1)<<2)); 
					block_y    =(((b8>>1)<<3)+((b4>>1)<<2));			 
					pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); 
					pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); 
					pic_pix_x  = (pic_block_x<<2); 
					pic_pix_y  = (pic_block_y<<2); 
					 
					ipredmode[pic_block_x+1][pic_block_y+1] = tmp_ipmode[b8][b4]; 
					 
					for(j=0;j<4;j++) 
						for(i=0;i<4;i++) 
							pgMbData->pred_sample[b8][b4][j][i] = tmp_Y[b8][b4][j][i]; 
						 
					for(j=0;j<2;j++) 
						for(i=0;i<18;i++) 
							cofAC[b8][b4][j][i] = tmp_cofAC[b8][b4][j][i]; 
				} 
			}	 
		} 
		else 
		{ 
			*min_cost = I_direct_cost; 
			pgMbHeader->I_MODE = 0/*1 dongjie(check) */; 
		}		 
	} 
	return *min_cost; 
} 
 
/* 
************************************************************************* 
* Function:Mode Decision for AVS intra blocks 
     This might also be placed in rdopt.c behind Mode_Decision_for_4x4IntraBlocks(). 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
//added by MAZHAN 
mpm[9][9] = 
{ 
	{0,	0,	2,	0,	0,	0,	2,	0,	2}, 
	{2,	1,	2,	2,	2,	2,	2,	2,	2}, 
	{2,	2,	2,	2,	2,	2,	2,	2,	2}, 
	{2,	1,	2,	3,	4,	5,	2,	7,	2}, 
	{4,	4,	2,	4,	4,	4,	6,	4,	4}, 
	{5,	5,	2,	5,	5,	5,	6,	5,	5}, 
	{6,	6,	6,	6,	6,	6,	6,	6,	6}, 
	{7,	7,	2,	7,	7,	7,	6,	7,	7}, 
	{0,	1,	2,	3,	4,	5,	6,	7,	8} 
}; 
 
int Mode_Decision_for_4x4IntraBlocks_luma(int b8, int b4, int *min_cost, int* coeff_cost)   //qwang 2004-3-5 
{ 
  int ipmode,best_ipmode,i,j; 
  int block_x; 
  int block_y; 
  int pic_pix_x; 
  int pic_pix_y; 
  int pic_block_x; 
  int pic_block_y; 
  int upMode; 
  int leftMode; 
  int mostProbableMode; 
  int lambda = pgMbData->lambda; 
  double lamda_mode = pgMbData->lamda_mode; 
  unsigned short cost; 
  int rate; 
  double rdcost, distortion; 
  int best_pred_sample[8][8]; 
  int diff_pix; 
 
  block_x    =(((b8 &1)<<3)+((b4 &1)<<2)); 
  block_y    =(((b8>>1)<<3)+((b4>>1)<<2)); 
  pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); 
  pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); 
  pic_pix_x  = (pic_block_x<<2); 
  pic_pix_y  = (pic_block_y<<2); 
   
  *min_cost = (1<<20); 
   
  //MZ 
  upMode           = ((ipredmode[pic_block_x+1][pic_block_y] == 10) ? -1 : ipredmode[pic_block_x+1][pic_block_y]); 
  leftMode         = ((ipredmode[pic_block_x][pic_block_y+1] == 10) ? -1 : ipredmode[pic_block_x][pic_block_y+1]); 
 
  mostProbableMode = (upMode < 0 || leftMode < 0) ? DC_PRED : mpm[leftMode][upMode]; //MAZHAN  
  
   
  //listing all the INTRA4x4 MODE 
  for (ipmode=0;ipmodeorg_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i];//imgY_org[pic_pix_y+j][pic_pix_x+i] - up_row_v; 
            cost += absm(diff_pix); // bug fix: index of diff was flipped. mwi 020701 
          } 
           
          if (cost < *min_cost) 
          { 
            best_ipmode = ipmode; 
            *min_cost   = cost; 
             
            for (j=0;j<4; j++) 
              for (i=0;i<4; i++) 
              { 
                best_pred_sample[j][i] = pgMbData->pred_curr[0][j][i]; 
              } 
          } 
      } 
      else //RDO 
      { 
        // reconstruct 
		 
		 // original frame subtract  pgMbData->pred_curr(curr_block's predicted values : performance in intrapred_luma()) 
        for (j=0;j<4; j++) 
          for (i=0;i<4; i++) 
          { 
            pgMbHeader->pred_residual[b8][b4][j][i] = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i]; 
          } 
         // save the predicted values into pgMbData->pred_sample  
        for (j=0;j<4; j++) 
          for (i=0;i<4; i++) 
          { 
            pgMbData->pred_sample[b8][b4][j][i] = pgMbData->pred_curr[0][j][i]; 
          }   
             
        Transform_B4(b8, b4); //based on residual data 
        Quant_B4(pgMbData->qp_mb, b8, b4, coeff_cost); 
 
        Save_RD_State(); 
         
        rate  = (ipmode == mostProbableMode) ? 1 : 3; 
		if(pgMbHeader->cbp_4x4[b8] & (1<byte_pos - pgRDStream->byte_pos)*8 + (pgRDStream->bits_to_go - pgcurrBitStream->bits_to_go); 
         
        Restore_RD_State(); 
         
        Dequant_B4(pgMbData->qp_mb,b8, b4); 
        Inv_Transform_B4(b8, b4); 
        Recon_B4(b8, b4, 0); 
         
		//Rec B4 
        for(j=0; j<4; j++) 
          for(i=0; i<4; i++)	 
          { 
            imgY[pic_pix_y+j][pic_pix_x+i] = imgY1[j][i];  
          } 
               
        //===== get distortion (SSD) of 4x4 block ===== 
        distortion = 0; 
        for (j=0; j<4; j++) 
          for (i=0; i<4; i++)   
            distortion += quadarr [original_frame[0][pic_pix_y+j][pic_pix_x+i] - imgY[pic_pix_y+j][pic_pix_x+i]]; 
           
          rdcost = (double)distortion + lamda_mode*(double)rate; 
           
        if(rdcost < *min_cost) 
        { 
          best_ipmode = ipmode; 
          pgMbHeader->luma_ipred_mode[b8][b4] = mostProbableMode == best_ipmode ? -1 : best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1; 
          pgMbHeader->luma_pred_mode_flag[b8][b4]  = mostProbableMode == best_ipmode;			   
          *min_cost   = (int) rdcost; 
          for (j=0; j<4; j++) 
            for (i=0; i<4; i++)  
              best_pred_sample[j][i] = pgMbData->pred_curr[0][j][i]; 
        } 
                 
      } 
    } 
  } 
 
  //===== set intra mode prediction ===== 
	//? 
  ipredmode[pic_block_x+1][pic_block_y+1] = best_ipmode;//zhangnan 
    pgMbHeader->luma_ipred_mode[b8][b4] = mostProbableMode == best_ipmode ? -1 : best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1; 
	pgMbHeader->luma_pred_mode_flag[b8][b4]  = mostProbableMode == best_ipmode; 
 
 
 
for (j=0; j<4; j++) 
	for (i=0; i<4; i++)  
		pgMbData->pred_sample[b8][b4][j][i] = best_pred_sample[j][i]; 
 
	// reconstruct 
	for (j=0;j<4; j++) 
		for (i=0;i<4; i++) 
		{ 
			pgMbHeader->pred_residual[b8][b4][j][i] = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_sample[b8][b4][j][i]; 
		} 
		 
	Transform_B4(b8, b4); 
	Quant_B4(pgMbData->qp_mb, b8, b4, coeff_cost); 
	Dequant_B4(pgMbData->qp_mb, b8, b4); 
	Inv_Transform_B4(b8, b4); 
	Recon_B4(b8, b4, 0); 
 
	for(j=0; j<4; j++) 
    for(i=0; i<4; i++)	 
    { 
      imgY[(pgMbData->mb_y<<4) + (b8/2)*8+(b4/2)*4+j][(pgMbData->mb_x<<4) + (b8%2)*8+(b4%2)*4+i] = imgY1[j][i]; //ÖØ½¨Öµ 
    } 
 
  return 1; 
} 
 
/* 
************************************************************************* 
* Function:calculate the RD_cost for intra direct mode. 
* Input: 
* Output: 
* Return:  
* Author: wjp 
************************************************************************* 
*/ 
int RD_cost_for_4x4_dir_IntraBlocks_luma(int b8, int b4, int *min_cost, int *dir_abort)   //qwang 2004-3-5 
{ 
	int coeff_cost; 
	int i,j; 
	int block_x; 
	int block_y; 
	int pic_pix_x; 
	int pic_pix_y; 
	int pic_block_x; 
	int pic_block_y; 
	int upMode; 
	int leftMode; 
	int mostProbableMode; 
	int lambda = pgMbData->lambda; 
	double lamda_mode = pgMbData->lamda_mode; 
	unsigned short cost; 
	int rate; 
	double rdcost, distortion; 
	int diff_pix; 
 
	block_x    =(((b8 &1)<<3)+((b4 &1)<<2)); 
	block_y    =(((b8>>1)<<3)+((b4>>1)<<2)); 
	pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); 
	pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); 
	pic_pix_x  = (pic_block_x<<2); 
	pic_pix_y  = (pic_block_y<<2); 
   
  //MZ 
  upMode           = ((ipredmode[pic_block_x+1][pic_block_y] == 10) ? -1 : ipredmode[pic_block_x+1][pic_block_y]); 
  leftMode         = ((ipredmode[pic_block_x][pic_block_y+1] == 10) ? -1 : ipredmode[pic_block_x][pic_block_y+1]); 
	//upMode           = ipredmode[pic_block_x+1][pic_block_y]; 
	//leftMode         = ipredmode[pic_block_x  ][pic_block_y+1]; 
 
  //*/  dsk 2004.6.15 
  //mostProbableMode = (upMode < 0 || leftMode < 0) ? DC_PRED : (upMode < leftMode ? upMode : leftMode);   
   mostProbableMode = (upMode < 0 || leftMode < 0) ? DC_PRED : mpm[leftMode][upMode]; 
   
	 ipredmode[pic_block_x+1][pic_block_y+1] = mostProbableMode; 
 
    //===== INTRA PREDICTION FOR 4x4 BLOCK ===== 
    if(intrapred_luma(pic_pix_x,pic_pix_y,mostProbableMode)) 
    { 
		 
		// reconstruct 
		for (j=0;j<4; j++) 
			for (i=0;i<4; i++) 
			{ 
				pgMbHeader->pred_residual[b8][b4][j][i] = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i]; 
			} 
			 
		for (j=0;j<4; j++) 
			for (i=0;i<4; i++) 
			{ 
				pgMbData->pred_sample[b8][b4][j][i] = pgMbData->pred_curr[0][j][i]; 
			}   
				 
		Transform_B4(b8, b4); 
		Quant_B4(pgMbData->qp_mb, b8, b4, &coeff_cost); 
		 
		Dequant_B4(pgMbData->qp_mb,b8, b4); 
		Inv_Transform_B4(b8, b4); 
		Recon_B4(b8, b4, 0); 
		 
		for(j=0; j<4; j++) 
			for(i=0; i<4; i++)	 
			{ 
				imgY[pic_pix_y+j][pic_pix_x+i] = imgY1[j][i];  
			} 
			 
		if(!input.rdopt) 
		{ 
			cost  = 0;   
			for (j=0;j<4;j++) 
				for (i=0;i<4;i++) 
				{ 
					diff_pix = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i];//imgY_org[pic_pix_y+j][pic_pix_x+i] - up_row_v; 
					cost += absm(diff_pix); // bug fix: index of diff was flipped. mwi 020701 
				} 
			*min_cost  = cost; 
		} 
		else 
		{ 
			//get the rate 
			Save_RD_State();			 
			rate  = 0;  
			if(pgMbHeader->cbp_4x4[b8] & (1<byte_pos - pgRDStream->byte_pos)*8 + (pgRDStream->bits_to_go - pgcurrBitStream->bits_to_go);			 
			Restore_RD_State(); 
			 
			//===== get distortion (SSD) of 4x4 block ===== 
			distortion = 0; 
			for (j=0; j<4; j++) 
				for (i=0; i<4; i++)   
					distortion += quadarr [original_frame[0][pic_pix_y+j][pic_pix_x+i] - imgY[pic_pix_y+j][pic_pix_x+i]]; 
           
			rdcost = (double)distortion + lamda_mode*rate; 
			*min_cost   = (int) rdcost; 
        }  
		 
    } 
	else 
	{ 
		*dir_abort = 1; 
	} 
	return 1; 
} 
 
 
/* 
************************************************************************* 
* Function: Select best Intra chroma prediction mode for a 8x8 block 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void IntraChromaPrediction8x8(int *mb_up,int *mb_left,int *mb_up_left) 
{ 
    int mode; 
    int i,j; 
    int best_mode; 
    double min_cost; 
    int img_cx = (pgMbData->mb_x<<3); 
    int	img_cy = (pgMbData->mb_y<<3); 
//	WJP FOR INTRA_CHROMA_S 050321 
 
    //MZ 
    int mb_available_up        = (ipredmode[(pgMbData->mb_x << 2)+1][(pgMbData->mb_y << 2)] >=0); 
   	int mb_available_left      = (ipredmode[(pgMbData->mb_x << 2)][(pgMbData->mb_y << 2)+1] >=0); 
    int mb_available_up_left   = (ipredmode[(pgMbData->mb_x << 2)][(pgMbData->mb_y << 2)] >=0); 
     
/*	  int mb_width             = pgImage->img_width/16; 
    int mb_available_up      = (pgMbData->mb_y == 0) ? 0 :  
							   (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width].slice_nr); 
    int mb_available_left    = (pgMbData->mb_x == 0) ? 0 :  
							   (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr); 
    int mb_available_up_left = (pgMbData->mb_y == 0 || pgMbData->mb_x == 0) ? 0 :  
							   (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width-1].slice_nr); 
//	WJP END 
*/ 
    int best_pred_sample[2][8][8]; 
    int rate; 
    int dummy; 
    int cost; 
    int bx ,by; 
 
    double distortion; 
    double rdcost; 
    int b8,b4; 
    int uv; 
 
	 
#ifdef _ISOLATED_REGION_ 
    //added by cbzhu, 2004.12.4 
    if (input.IREGEnable) 
    { 
        if (pgImage->type == INTER_IMG) 
        { 
            if (mb_available_up != 0) 
            { 
                if (pCurrFrmIREGMap[pgImage->mb_y - 1][pgImage->mb_x] != 2) 
                { 
                    mb_available_up = 0; 
                } 
            } 
            if (mb_available_left != 0) 
            { 
                if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x - 1] != 2) 
                { 
                    mb_available_left = 0; 
                } 
            } 
            if (mb_available_up_left != 0) 
            { 
                if (pCurrFrmIREGMap[pgImage->mb_y - 1][pgImage->mb_x - 1] != 2) 
                { 
                    mb_available_up_left = 0; 
                } 
            } 
        } 
    } 
#endif // _ISOLATED_REGION_ 
 
    if (mb_up)          *mb_up = mb_available_up; 
    if (mb_left)        *mb_left = mb_available_left; 
    if (mb_up_left )    *mb_up_left = mb_available_up_left; 
    best_mode = DC_PRED_8; //0 
    min_cost = 1<<20; 
    for (mode = DC_PRED_8; mode <= VERT_PRED_8; mode++) 
    { 
        cost = 0; 
        if ((mode == VERT_PRED_8 && !mb_available_up) || 
            (mode == HOR_PRED_8  && !mb_available_left))  //(mode == PLANE_8     && (!mb_available_left || !mb_available_up || !mb_available_up_left)) 
        { 
            continue; 
        } 
        for (b4 = 0; b4 < 4; b4++) 
        { 
 
            intrapred_chroma_4x4(pgMbData->mb_x,pgMbData->mb_y,b4,mode); 
 
			 
            bx = (b4 &1)<<2; 
            by = (b4>>1)<<2; 
            for (uv=0; uv<2;uv++) 
            { 
                for(j=0;j<4;j++)     //y 
                { 
                    for(i=0;i<4;i++) //x 
                    { 
                        pgMbHeader->pred_residual[4+uv][b4][j][i]  
                            = pgMbData->org_chroma[uv][by+j][bx+i] - pgMbData->pred_curr[uv][by+j][bx+i]; 
                        pgMbData->pred_sample[4+uv][b4][j][i]  
                            = pgMbData->pred_curr[uv][by+j][bx+i]; 
					} 
                } 
				 
				Transform_B4(4+uv, b4); 
				Quant_B4(pgMbData->qp_mb, 4+uv, b4, &dummy); 
				Dequant_B4(pgMbData->qp_mb, 4+uv, b4); 
				Inv_Transform_B4(4+uv, b4);  
				Recon_B4(4+uv, b4, 0);	 
				for(j=0; j<4; j++)      //y 
				{ 
					for(i=0; i<4; i++)	//x 
					{ 
						imgUV[uv][(pgMbData->mb_y<<3) + (b4/2)*4+j][(pgMbData->mb_x<<3) +(b4%2)*4+ i]  
							= imgUV1[uv][j][i];  
					} 
				} 
            } 
 
        } 
 
        if(!input.rdopt) // NO RD optimization 
        { 
            for (uv=0; uv<2;uv++) 
            { 
                for (j=0;j<8;j++)//y 
                { 
                    for(i=0;i<8;i++)//x 
                    { 
                        cost += absm(pgMbData->org_chroma[uv][j][i]  
                            - pgMbData->pred_curr[uv][j][i]); 
                    } 
                } 
            } 
            if (cost < min_cost) 
            { 
                best_mode = mode; 
                min_cost = cost; 
 
                for (uv=0; uv<2;uv++) 
                { 
                    for (j=0; j<8; j++) 
                    { 
                        for (i=0; i<8; i++) 
                        { 
                            best_pred_sample[uv][j][i] = pgMbData->pred_curr[uv][j][i]; 
 
                        } 
                    } 
                } 
            } 
        } 
        else // RD OPT 
        { 
 
            Save_RD_State(); 
            ue_linfo(mode); 
            for (b8=4; b8<6; b8++) 
            { 
                for (b4=0; b4<4; b4++) 
                {			 
					if(pgMbHeader->cbp_4x4[b8] & (1<byte_pos - pgRDStream->byte_pos)*8  
                + (pgRDStream->bits_to_go-pgcurrBitStream->bits_to_go); 
            Restore_RD_State();//qwang 2004-3-15 
            distortion = 0; 
            for(uv=0; uv<2; uv++) 
            { 
                for(j=0; j<8; j++) 
                { 
                    for(i=0; i<8; i++) 
                    { 
                        distortion +=  
                            quadarr[pgMbData->org_chroma[uv][j][i]-imgUV[uv][img_cy+j][img_cx+i]]; 
                    } 
                } 
            } 
            rdcost = distortion + pgMbData->lamda_mode*rate; 
            if(rdcostpred_curr[uv][j][i]; 
 
                        } 
                    } 
                } 
            }//end if(rdcostmb_x+1][pgMbData->mb_y+1] = best_mode; 
    pgMbHeader->chroma_ipred_mode = best_mode; 
 
    for(uv=0;uv<2;uv++)  // zhangnan 
    for (j=0; j<8; j++) 
    for (i=0; i<8; i++) 
    { 
        pgMbHeader->pred_residual[4+uv][i/4+(j/4)*2][j%4][i%4]  
            = pgMbData->org_chroma[uv][j][i] - best_pred_sample[uv][j][i]; 
        pgMbData->pred_sample[4+uv][i/4+(j/4)*2][j%4][i%4] 
            = best_pred_sample[uv][j][i]; 
    } 
} 
 
 
/* 
************************************************************************* 
* Function:  
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void intrapred_chroma_4x4(  int mb_x,     // mb x-pos in mb unit 
                            int mb_y,     // mb y-pos in mb unit 
                            int b4,       // subblock number 
                            int mode)     // chroma pred 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        = (ipredmode[(mb_x << 2)+1][(mb_y << 2)] >=0); 
   	int mb_available_left      = (ipredmode[(mb_x << 2)][(mb_y << 2)+1] >=0); 
    int mb_available_up_left   = (ipredmode[(mb_x << 2)][(mb_y << 2)] >=0); 
     
 
/*	 
    int mb_width             = pgImage->img_width/16; 
    int mb_available_up      = (pgMbData->mb_y == 0) ? 0 :  
							                 (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width].slice_nr); 
    int mb_available_left    = (pgMbData->mb_x == 0) ? 0 :  
							                 (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr); 
 
    int mb_available_up_left = (pgMbData->mb_x == 0 || pgMbData->mb_y == 0) ? 0 :  
	                             (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width-1].slice_nr);							    
*/	 
    // 
    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_curr[0][by+y][bx+x] = u0; 
			pgMbData->pred_curr[1][by+y][bx+x] = v0; 
		  } 
		} 
		break; 
    case HOR_PRED_8: 
        if (block_available_left) 
        { 
            for (y=0;ypred_curr[0][by+y][bx+x] = vlineU[y]; 
                    pgMbData->pred_curr[1][by+y][bx+x] = vlineV[y]; 
                } 
            } 
        } 
        break; 
    case VERT_PRED_8: 
        if (block_available_up) 
        { 
            for (x=0;xpred_curr[0][by+y][bx+x] = hlineU[x]; 
                    pgMbData->pred_curr[1][by+y][bx+x] = hlineV[x]; 
                } 
            } 
             
        } 
        break; 
     default: 
		 fprintf(stderr,"Error in intrapred_chroma\n"); 
        break; 
        } 
} 
 
 
 
 
/* 
************************************************************************* 
* Function:Intra chroma prediction for every 8x8 block 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
int Intra_Chroma_Prediction (int * min_cost)   //zhangnan 
{ 
	int b8,b4,i,j; 
	int dummy; 
	 
	IntraChromaPrediction8x8(NULL, NULL, NULL);	 
     
	//sw Chroma DC 
	for (b8=4; b8<6; b8++) 
	{ 
		for (b4=0; b4<4; b4++) 
		{ 
			Transform_B4(b8, b4); 
		} 
		 
	//TranformChromaDC(b8); 
		 
		for (b4=0; b4<4; b4++) 
		{	 
			Quant_B4(pgMbData->qp_mb, b8, b4, &dummy); 
		} 
		// dongjie 
		if(pgMbHeader->cbp_4x4[b8]==0) 
			pgMbHeader->cbp &= (~(1<cbp |= (1<qp_mb, b8, b4); 
		} 
		 
  	//InvTransformChromaDC(b8); 
		 
		for (b4=0; b4<4; b4++) 
		{ 
			Inv_Transform_B4(b8, b4);  
			 
			Recon_B4(b8, b4, 0); 
			for(j=0; j<4; j++) 
				for(i=0; i<4; i++)	 
				{ 
					imgUV[b8-4][(pgMbData->mb_y<<3) + (b4/2)*4+j][(pgMbData->mb_x<<3) +(b4%2)*4+ i] = imgUV1[b8-4][j][i];  
				} 
		} 
	} 
	 
	return 1; 
}