www.pudn.com > wm2.5.zip > picture.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  
 
#include "global.h" 
#include "define.h" 
#include "macroblock.h" 
#include "block.h" 
#include "intrapred.h" 
#include "interpred.h" 
#include "picture.h" 
#include "vlc.h" 
#include "types.h" 
#include "block_const.h" 
#include "rdopt.h" 
#include "loopfilter.h" 
#include "nalu.h"//WJP FOR NAL 
#include "parset.h"//cbzhu 041221 
 
#include "ratectl.h"          // LX 0409 
 
#define Clip(a, b, c) max (a, min (b, c)) 
 
extern void Form_RBSP(Bitstream *currBitStream); 
//! convert from H.263 QP to H.26L quant given by: quant=pow(2,QP/6) 
const int QP2QUANT[40]= 
{ 
    1, 1, 1, 1, 2, 2, 2, 2, 
    3, 3, 3, 4, 4, 4, 5, 6, 
    6, 7, 8, 9,10,11,13,14, 
    16,18,20,23,25,29,32,36, 
    40,45,51,57,64,72,81,91 
}; 
 
extern const int BITSMBTYPE[6];                //qwang 2004-3-24 
const int Mv_Block_Size[4][2] = {{16,16},{16,8},{8,16},{8,8}}; 
 
//WJP FOR SLICE 
/******************************************************************** 
	Created:	2004.9.18   
	Author :	Jianpeng Wang 
	Input  : 
	Output : 
 
	Function:  Encode Slice Header 	 
*********************************************************************/ 
void SliceHeader(int first_mb_nr_in_slice,int slice_qp)//WJP FOR SLICE_HEADER 050320 
{ 
/*WJP FOR SLICE_HEADER 050320 
	/ *WJP FOR NAL 
	u_v(24,"start code prefix",1);* / 
	u_v(8,"Slice start code", Pos_Slice); 
	first_mb_nr_in_slice = pgImage->current_mb_nr; 
*/ 
	int delta_qp; 
	delta_qp = slice_qp - pgImage->qp; 
	ue_linfo(first_mb_nr_in_slice); 
	 
//WJP END 
 
	if(!pgImage->fixed_picture_qp) 
	{ 
		u_v(1,"fixed_slice_qp",1); 
//		u_v(6,"slice_qp",slice_qp);WJP FOR SLICE_HEADER 050320 
		se_linfo(delta_qp);		 
	} 
	//WJP FOR SLICE_DEBLOCK 050321 
	if(!active_pps->loop_filter_disable_flag) 
		u_v(1, "disable_loop_filter_slice_flag", pgImage->disable_loop_filter_slice_flag); 
	//WJP END 050321 
} 
/******************************************************************** 
	Created:	2004.9.18   
	Author :	Jianpeng Wang 
	Input  : 
	Output : 
 
	Function:  Terminate a Slice 	 
*********************************************************************/ 
void terminate_slice(int mb_x, int mb_y) 
{ 
/*WJP FOR SLICE_HEADER 050320 
	assert (input.slice_parameter>0 && input.slice_parameter<=input.img_height/MB_BLOCK_SIZE); 
	if((mb_x==input.img_width / MB_BLOCK_SIZE-1)&&!((mb_y+1)%input.slice_parameter)) 
*/ 
	assert (input.slice_parameter>0 && input.slice_parameter<=(input.img_height/MB_BLOCK_SIZE)*(input.img_width/MB_BLOCK_SIZE)); 
	if(!(pgImage->current_mb_nr%input.slice_parameter) 
		||pgImage->current_mb_nr == input.img_height*input.img_width/MB_BLOCK_SIZE/MB_BLOCK_SIZE) 
//WJP END		 
	{		 
		pgImage->current_slice_nr++; 
		Form_RBSP(pgcurrBitStream);//WJP FOR NAL	 
	} 
} 
//WJP END 
/******************************************************************** 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
  Output : 
 
	Function:  Encode I frame 	 
*********************************************************************/ 
void Encode_I_Frame(void) 
{ 
	int mb_x, mb_y; 
	int img_x, img_y; 
	int dummy; 
	int mb_nr=0; 
 
	pgImage->picture_code_type = INTRA_IMG; 
	pgImage->p_pic_type = 0; 
 
	if(!input.RCEnable) 
	{ 
		pgMbData->lambda = QP2QUANT[max(0, pgImage->qp0 - 11)];   //qwang 2004-3-18  pgImage->qp0 - 11 
	  pgMbData->lamda_mode = 0.85*pow(2, (pgImage->qp0 - 11)/4.0);  
	} 
	else 
	{ 
		pgMbData->lambda     = QP2QUANT[max(0, pgMbData->qp_mb - 11)];      // LX 0409 
		pgMbData->lamda_mode = 0.85*pow(2, (pgMbData->qp_mb - 11)/4.0);     // LX 0409 
	} 
	 
	pgMbHeader->mb_type = I4MB; 
 
	//write I picture header 
	//I_Picture_Header(); 
	write_PicHeader(picture_header_rbsp);    //cbzhu 0412 
 
	pgImage->current_mb_nr=0; 
	//WJP FOR SLICE 
	pgImage->current_slice_nr=0; 
	pgImage->disable_loop_filter_slice_flag = 1;//WJP FOR SLICE_DEBLOCK 050321 
	for(dummy=0;dummyqp_mb = pgImage->qp0;     // LX 0409 
	 
	for(mb_y=0, img_y=0; img_yimg_height; img_y+=16, mb_y++) 
	for(mb_x=0, img_x=0; img_ximg_width ; img_x+=16, mb_x++) 
	{ 
		pgMbData->mb_x = mb_x; 
		pgMbData->mb_y = mb_y; 
		//WJP FOR SLICE 
		pgImage->mb_y = mb_y; 
		pgImage->mb_x = mb_x; 
		//WJP END 
		 
		Init_Macroblock(img_x, img_y); 
		//WJP FOR SLICE 
		if(input.slice) 
		{ 
			if(pgImage->current_mb_nr==0 || ( pgImage->current_mb_nr>0 &&  
				(pgImage->current_slice_nr != pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr) )) 
			{ 
				//Form_RBSP(pgcurrBitStream);//WJP FOR NAL 
				assert(pgImage->current_slice_nrcurrent_slice_nr]=pgcurrBitStream->byte_pos;				 
				SliceHeader(pgImage->current_mb_nr,pgImage->qp0);//WJP FOR SLICE_HEADER 050320 
			} 
		} 
		//WJP END 
		Intra_Luma_Prediction(&dummy); 
		Intra_Chroma_Prediction(&dummy);  //zhangnan  
		 
		//write one macroblock to bitstream 
		write_one_macroblock (); 
 
		Output_Macroblock(img_x, img_y); //write reconstructed image to memory 
		mb_nr++; 
		pgMbHeader->cbp_blk=0; 
		pgImage->mb_headerdata[pgImage->current_mb_nr] = * pgMbHeader; 
		pgImage->mb_data_forlf[pgImage->current_mb_nr] = * pgMbData; 
		pgImage->current_mb_nr++; 
		//WJP FOR SLICE 
		if(input.slice) 
		{ 
			terminate_slice(mb_x, mb_y);			 
		} 
		//WJP END 
	} 
 
	DeblockFrame(pgImage , current_frame); 
} 
 
/******************************************************************** 
	Created:	12:2:2004 
	Author :	Siwei Ma 
	Input  : 
  Output : 
 
	Function:  Encode P frame 	 
*********************************************************************/ 
 
void Encode_P_Frame(void)       //qwang 2004-3-20 
{ 
  int mb_x, mb_y; 
  int img_x, img_y; 
  int i, j; 
  int min_cost_intra; 
  int dummy; 
  int min_cost_inter; 
  int inter_mode; 
 
  double validbits;                   // LX 0409 
  CurrentFrameLValidbits = 0;      // LX 0409 
   
  //cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
  if(input.IREGEnable) 
  { 
	  intrambcount=0; 
  } 
#endif 
  pgImage->current_mb_nr=0; 
  //WJP FOR SLICE 
  pgImage->current_slice_nr=0; 
  pgImage->disable_loop_filter_slice_flag = 1;//WJP FOR SLICE_DEBLOCK 050321 
  for(i=0;ipicture_code_type = INTER_IMG; 
 
  if(input.spframe == 0) 
  { 
    pgImage->p_pic_type = 0; 
  } 
  else 
  { 
    pgImage->p_pic_type = 1 - pgImage->p_pic_type; 
  } 
   
  if(!input.RCEnable) 
  {   
	  //pgMbData->lambda = QP2QUANT[max(0, pgImage->qpN - 11)];  //qwang 2004-3-18   -11 
	  //pgMbData->lamda_mode = 0.85*pow(2, (pgImage->qpN - 11)/4.0);   
	   
	  //Hou huiman 2004-10-28-----start 
	  //non reference P frame , accepted as M1445  
	  //added by cbzhu , Nov 13 2004 
/**/if(pgImage->p_pic_type==0/*1 dongjie(check) */) 
	 { 
	  pgMbData->lambda = QP2QUANT[max(0, pgImage->qpN - 11)];  //qwang 2004-3-18   -11 
	  pgMbData->lamda_mode = 0.85*pow(2, (pgImage->qpN - 11)/4.0);  //2.5 
	  pgMbData->lamda_motion = sqrt(pgMbData->lamda_mode);   
 
	  pgMbData->qp_mb = pgImage->qpN;  
	  
	 } 
	else 
	{ 
	 pgMbData->lambda = QP2QUANT[max(0, pgImage->qpN - 11)];  //qwang 2004-3-18   -11 
	 pgMbData->lamda_mode = 0.90/* dongjie(check) 0.80*/*pow(2, (pgImage->qpN - 11)/4.0);  //0.6 
	 pgMbData->lamda_motion = sqrt(pgMbData->lamda_mode);   
 
   	 pgMbData->qp_mb = pgImage->qpN-1;   
 
	} 
	//Hou huiman-------end 
  } 
  else 
  {	   
	  pgMbData->lambda     = QP2QUANT[max(0, pgMbData->qp_mb - 11)]; 
	  pgMbData->lamda_mode = 0.85*pow(2, (pgMbData->qp_mb - 11)/4.0);  
  
  } 
   
  pgMbData->lamda_motion = sqrt(pgMbData->lamda_mode); 
   
  pgImage->cod_counter = 0; 
 
  pgImage->half_pixel_mv_flag = pgImage->half_pixel_mv_enable_flag; //Yulejun 2004.Sep.04.  
   
  //write out P picuture header 
  //P_Picture_Header(); 
  write_PicHeader(picture_header_rbsp);   //cbzhu 0412 
   
  //if(!input.RCEnable)                          // LX 0409 
  //		pgMbData->qp_mb = pgImage->qpN;        // LX 0409 
  //deleted by Hou huiman  
 
  for(mb_y=0, img_y=0; img_yimg_height; img_y+=16, mb_y++) 
    for(mb_x=0, img_x=0; img_ximg_width ; img_x+=16, mb_x++) 
    { 
       pgMbData->mb_x = mb_x; 
       pgMbData->mb_y = mb_y; 
       pgImage->mb_y = mb_y; 
       pgImage->mb_x = mb_x; 
        
       Init_Macroblock(img_x, img_y); 
	   //WJP FOR SLICE 
	   if(input.slice) 
	   { 
		   if(pgImage->current_mb_nr==0 || ( pgImage->current_mb_nr>0 &&  
			   (pgImage->current_slice_nr != pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr) )) 
		   { 
			   //Form_RBSP(pgcurrBitStream); WJP FOR NAL 
			   assert(pgImage->current_slice_nrcurrent_slice_nr]=pgcurrBitStream->byte_pos;				 
			   SliceHeader(pgImage->current_mb_nr,pgImage->qpN);//WJP FOR SLICE_HEADER 050320 
		   } 
	   } 
	   //WJP END 
       min_cost_inter = Inter_Modes_Decision(); 
        
       if(!input.rdopt) 
       { 
         pgMbHeader->mb_type = I4MB; 
         min_cost_intra  = Intra_Luma_Prediction(&dummy); 
         min_cost_intra += MODE_COST(LAMBDA_FACTOR(pgMbData->lambda), BITSMBTYPE[I4MB]);           //qwang 2004-3-24 
          
         //--- Update ref info ... delay one macroblock --- 
         if(mb_x > 0) 
         { 
           pgMbData->up_row_ref[mb_x - 1] = pgMbData->left_ref; 
         } 
         else 
         {	// Update the last pos in the begin of next row 
           pgMbData->up_row_ref[pgImage->img_width/16 - 1] = pgMbData->left_ref; 
         } 
          
         /////////////////////////////////////////////// 
         // Mode decision 
          
         //select INTRA 
         inter_mode = (min_cost_inter <= min_cost_intra); 
          
         if (!inter_mode) 
         { 
           pgMbHeader->mb_type = I4MB; 
           pgMbData->left_ref = -1; 
            
           for (j = 0; j < 4; j++) 
             for (i = 0; i < 4; i++) 
             { 
               tmp_mv[0][pgMbData->mb_y*4+j][pgMbData->mb_x*4+i+4] = 0; 
               tmp_mv[1][pgMbData->mb_y*4+j][pgMbData->mb_x*4+i+4] = 0; 
               refFrArr  [pgMbData->mb_y*4+j][pgMbData->mb_x*4+i  ] = -1; 
             } 
              
             Intra_Chroma_Prediction(&dummy); 
 
             //write one macroblock to bitstream 
             write_one_macroblock (); 
         } 
       } 
       else 
         inter_mode = RD_Cost_Inter_Macrobock(); 
 
       if(inter_mode) 
       { 
         Code_Inter_Macroblock(); 
       } 
 
	   //cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
       if (input.IREGEnable) 
       { 
           if (pCurrFrmIREGMap[mb_y][mb_x] != 2) 
           { 
               for (j = 0; j < 4; j++) 
               { 
                   for (i = 0; i < 4; i++) 
                   { 
                       ipredmode[mb_x * 4 + i + 1][mb_y * 4 + j + 1] = -1; 
                   } 
               } 
           } 
       } 
#endif // _ISOLATED_REGION_ 
	    
       // LX 0409 
	   validbits = 0; 
	 
	   for ( j = 0; j < MB_BLOCK_SIZE; j++) 
		   for ( i = 0; i < MB_BLOCK_SIZE; i++) 
		   { 
			   if ( g_nbestDCTcoef[i][j] != 0 ) 
			   { 
				   // 除以最小量化间隔, 若小于 1 则不计算有效比特长 
				   g_nbestDCTcoef[i][j] = g_nbestDCTcoef[i][j] * DCTscale[i%4][j%4] / 0.625; 
				   if (g_nbestDCTcoef[i][j] < 1) 
				   { 
					   continue; 
				   } 
				   else 
				   { 
					   validbits  = log(absm(g_nbestDCTcoef[i][j]))/log(2) + 1;  
				   }                  
			   } 
		   } 
		    
		CurrentFrameLValidbits += validbits; 
		// LX 0409 
 
		    
       //--- write reconstructed image to memory --- 
       Output_Macroblock(img_x,img_y);  
 
       //save for loopfilter          cbzhu 
       pgMbHeader->cbp_blk=0; 
       pgImage->mb_headerdata[pgImage->current_mb_nr] = * pgMbHeader; 
       pgImage->mb_data_forlf[pgImage->current_mb_nr] = * pgMbData; 
 
	   //if( pgImage->current_mb_nr == 17) 
		//   printf("%d \n" , pgMbHeader->mb_type); 
       pgImage->current_mb_nr++;     
	   //WJP FOR SLICE 
	   if(input.slice) 
	   { 
		   terminate_slice(mb_x, mb_y);			 
	   } 
	   //WJP END 
	   //printf("%d \n " , pgMbHeader->mb_type); 
    } 
     
	DeblockFrame(pgImage , current_frame); 
 
} 
 
/******************************************************************** 
	Created:	13:2:2004   
	Author :	Siwei Ma 
	Input  :     
    Output : 
 
	Function:	 
*********************************************************************/ 
void Padding_IP_Frame(void) 
{ 
	int i, j; 
	int ii, jj; 
 
	for (j = -PAD_SIZE; j < pgImage->img_height + PAD_SIZE; j++) 
	{ 
		for (i = -PAD_SIZE; i < pgImage->img_width + PAD_SIZE; i++) 
		{ 
			jj = max (0, min (pgImage->img_height - 1, j)); 
            ii = max (0, min (pgImage->img_width  - 1, i));  
			 
            //store 1/1 pixel value 
            current_frame[0][j + PAD_SIZE][i + PAD_SIZE] = current_frame[0][jj + PAD_SIZE][ii + PAD_SIZE];// 1/1 pix pos 
		} 
	}	 
} 
/******************************************************************** 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
    Output : 
 
	Function:  Interpolation	 
    Note   :   Aug 10, 2004, accept M1323(北京工业大学), added by yiwang 
*********************************************************************/ 
 
/* 
void Interpolate_IP_Frame(void) 
{ 
	int TapArr1_2[4] = { -1, 5, 5, -1}; 
	 
	int TapArr1_4a[3] = { 8, 7, 1}; 
	int TapArr1_4b[3] = { 1, 7, 8}; 
	int TapArr1_4c[3] = { 7, 7, 2};  
	int TapArr1_4d[3] = { 2, 7, 7}; 
	 
 
	int iWeight1_2 = 8; 
	int iWeight1_4a = 16; 
	int iWeight1_4b = 16; 
	int iWeight1_4c = 16; 
	int iWeight1_4d = 16; 
	int is; 
	int i, j;// j4; 
	int ie2, je2; 
	int maxy, maxx;  
	int ii, jj, yy; 
	int val; 
 
		//Half pel interpolation to half-pel reference buffer 
		//horizonal 1/2 interpolation 
		maxx = pgImage->img_width + 2 * PAD_SIZE - 1; 
		for (j = -PAD_SIZE; j < pgImage->img_height + PAD_SIZE; j++) 
		{ 
			jj = j + PAD_SIZE; 
			for (i = -PAD_SIZE; i < pgImage->img_width + PAD_SIZE; i++) 
			{ 
				ii = i + PAD_SIZE; 
				val = 
					  TapArr1_2[0] * current_frame[0][jj][Clip(0, maxx, ii - 1)]  
					+ TapArr1_2[1] * current_frame[0][jj][ii                   ]  
					+ TapArr1_2[2] * current_frame[0][jj][Clip(0, maxx, ii + 1)]  
					+ TapArr1_2[3] * current_frame[0][jj][Clip(0, maxx, ii + 2)]; 
 
				//store 1/1 pixel value 
				half_pel_frame_tmp[0][2 * jj][2 * ii]  
					= current_frame[0][jj][Clip(0, maxx, ii)] * 1024;// 1/1 pix pos 
				//store horizonal 1/2 pixel value 
				half_pel_frame_tmp[0][2 * jj][2 * ii + 1] = val * 1024 / iWeight1_2;// 1/2 pix pos 
			} 
		} 
 
  	//vertical 1/2 interpolation 
		maxy = 2 * (pgImage->img_height + 2 * PAD_SIZE) - 2; 
		for (i = 0; i < (pgImage->img_width + 2 * PAD_SIZE) * 2; i++)  
		{ 
			for (j = 0; j < pgImage->img_height + 2 * PAD_SIZE; j++) 
			{	 
				 
				is = 
					( 	TapArr1_2[0] * half_pel_frame_tmp[0][max(0, 2 * j - 2)   ][i]  
					  +	TapArr1_2[1] * half_pel_frame_tmp[0][min(maxy, 2 * j)    ][i]  
					  + TapArr1_2[2] * half_pel_frame_tmp[0][min(maxy, 2 * j + 2)][i]  
					  + TapArr1_2[3] * half_pel_frame_tmp[0][min(maxy, 2 * j + 4)][i]   
					    
					) / iWeight1_2; 
 
				//vertical half pel 
				yy = min(maxy, 2 * j); 
				val = (int) ( ( half_pel_frame_tmp[0][yy][i] + 512 ) / 1024 ); 
				reference_half_pel_frame[0][j * 2    ][i] =  Clip(0, 255, val); 
 
				val = (int) ( ( is + 512 ) / 1024 ); 
				reference_half_pel_frame[0][j * 2 + 1][i] =  Clip(0, 255, val); 
 
				reference_quater_pel_frame[0][4 * j    ][2 * i]  
					= reference_half_pel_frame[0][j * 2][i]; 
				reference_quater_pel_frame[0][4 * j + 2][2 * i]  
					= reference_half_pel_frame[0][j * 2 + 1][i]; 
			} 
		} 
 
		//Quater pel intepolation 
		// 1/4 pix 
		// luma 
		ie2 = (pgImage->img_width  + 2 * PAD_SIZE - 1) * 4; 
		je2 = (pgImage->img_height + 2 * PAD_SIZE - 1) * 4; 
 
		//horizonal 1/4 interpolation 
		for (j = 0; j < je2 + 4; j += 2) 
		{ 
			for (i = 0; i < ie2 + 3; i += 2) 
			{ 
				//  '-' 
				if(j % 4 == 0) 
				{ 
					if(i % 4 == 0) 
					{ 
						val = (int) ( 
							( 
							TapArr1_4a[0] * reference_quater_pel_frame[0][j][i                   ]  
							+ TapArr1_4a[1] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] 
							+ TapArr1_4a[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] 
							+ iWeight1_4a / 2 ) 
							) / iWeight1_4a ; 
						reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); 
					}else{ 
						val = (int) ( 
							( 
							TapArr1_4b[0] * reference_quater_pel_frame[0][j][max(0, i - 2)       ] 
							+ TapArr1_4b[1] * reference_quater_pel_frame[0][j][i                   ]  
							+ TapArr1_4b[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] 
							+ iWeight1_4b / 2 ) 
							) / iWeight1_4b ; 
						reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); 
					} 
				}else{ 
					if(i % 4 == 0) 
					{ 
						val = (int) ( 
							( 
							TapArr1_4c[0] * reference_quater_pel_frame[0][j][i                   ]  
							+ TapArr1_4c[1] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] 
							+ TapArr1_4c[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] 
							+ iWeight1_4c / 2 ) 
							) / iWeight1_4c ; 
						reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); 
					}else{ 
						val = (int) ( 
							( 
							TapArr1_4d[0] * reference_quater_pel_frame[0][j][max(0, i - 2)       ] 
							+ TapArr1_4d[1] * reference_quater_pel_frame[0][j][i                   ]  
							+ TapArr1_4d[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] 
							+ iWeight1_4d / 2 ) 
							) / iWeight1_4d ; 
						reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); 
					} 
				}  
					 
			} 
		} 
		 
  	//vertical 1/4 interpolation 
		for (i = 0; i < ie2 + 4; i++) 
		{ 
			for (j = 0; j < je2 + 3; j += 2) 
			{ 
				// '|' 
				if (i % 4 == 0) 
				{ 
					if(j % 4 == 0) 
					{ 
						val = (int) ( 
							(  
							TapArr1_4a[0] * reference_quater_pel_frame[0][j                  ][i] 
							+ TapArr1_4a[1] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] 
							+ TapArr1_4a[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] 
							+ iWeight1_4a / 2 )  
							/ iWeight1_4a ); 
						 
						reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
					}else{ 
						val = (int) ( 
							(  
							TapArr1_4b[0] * reference_quater_pel_frame[0][max(0, j - 2)      ][i] 
							+ TapArr1_4b[1] * reference_quater_pel_frame[0][j                  ][i] 
							+ TapArr1_4b[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] 
							+ iWeight1_4b / 2 )  
							/ iWeight1_4b ); 
						 
						reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
					} 
				} 
				else if(i % 4 == 2) 
				{ 
					if(j % 4 == 0) 
					{ 
						val = (int) ( 
							(  
							TapArr1_4c[0] * reference_quater_pel_frame[0][j                  ][i] 
							+ TapArr1_4c[1] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] 
							+ TapArr1_4c[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] 
							+ iWeight1_4c / 2 )  
							/ iWeight1_4c ); 
						 
						reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
					}else{ 
						val = (int) ( 
							(  
							TapArr1_4d[0] * reference_quater_pel_frame[0][max(0, j - 2)      ][i] 
							+ TapArr1_4d[1] * reference_quater_pel_frame[0][j                  ][i] 
							+ TapArr1_4d[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] 
							+ iWeight1_4d / 2 )  
							/ iWeight1_4d ); 
						 
						reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
					} 
				} 
				else if (j % 4 == 0 && i % 4 == 1) 
				{ 
					// '\' 
					val = (int) ( 
						( reference_quater_pel_frame[0][j                  ][max(0, i - 1)      ]  
						+ reference_quater_pel_frame[0][min(je2 + 2, j + 2)][min(ie2 + 2, i + 1)] 
						+ 1 ) / 2); 
					reference_quater_pel_frame[0][j + 1][i] =  Clip(0, 255, val); 
				} 
				else if(j % 4 == 2 && i % 4 == 3) 
				{ 
					val = (int) ( 
						( reference_quater_pel_frame[0][j              ][max(0, i - 1)  ] 
						+ reference_quater_pel_frame[0][min(je2, j + 2)][min(ie2, i + 1)] 
						+ 1) / 2); 
					reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
				} 
				else if(j % 4 == 0 && i % 4 == 3) 
				{ 
					//  '/' 
					val = (int) ( 
						( reference_quater_pel_frame[0][j                  ][min(ie2, i + 1)] 
						+ reference_quater_pel_frame[0][min(je2 + 2, j + 2)][max(0, i - 1)  ] 
						+ 1) / 2); 
					reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
				} 
				else if(j % 4 == 2 && i % 4 == 1) 
				{ 
					//  '/' 
					val = (int) ( 
						( reference_quater_pel_frame[0][j              ][min(ie2 + 2, i + 1)]  
						+ reference_quater_pel_frame[0][min(je2, j + 2)][max(0, i - 1)      ] 
						+ 1 ) / 2 ); 
					reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
				} 
			}//for (j = 0; j < je2 + 3; j += 2) 
		}//for (i = 0; i < ie2 + 4; i++)	 
} 
 
 
*/ 
 
/******************************************************************** 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
    Output : 
 
	Function:  Interpolation	 
    Note   :   Nov 13, 2004, accept M1466(北京工业大学), added by cbzhu 
*********************************************************************/ 
void Interpolate_IP_Frame(void) 
{ 
	int TapArr1_2_h[4][2] =  
	{ 
		{41,20}, 
		{-12,-4}, 
		{ 4, 0}, 
		{ -1, 0} 
	}; 
	 
	int TapArr1_2_v[4][2] =  
	{ 
		{5,20}, 
		{-1,-4}, 
		{ 0, 0}, 
		{ 0, 0} 
	}; 
	 
	int iWeight1_2_h = 64; 
	int iWeight1_2_v = 8; 
	 
	 
	int TapArr1_4[4] = { 0, 1, 1, 0}; 
	int iWeight1_4 = 2; 
 
	 
	int is; 
	int i, j;// j4; 
	int ie2, je2; 
	int maxy, maxx;  
	int ii, jj, yy; 
	int val; 
 
		//Half pel interpolation to half-pel reference buffer 
		//horizonal 1/2 interpolation 
		maxx = pgImage->img_width + 2 * PAD_SIZE - 1; 
		for (j = -PAD_SIZE; j < pgImage->img_height + PAD_SIZE; j++) 
		{ 
			jj = j + PAD_SIZE; 
			for (i = -PAD_SIZE; i < pgImage->img_width + PAD_SIZE; i++) 
			{ 
				ii = i + PAD_SIZE; 
				val =(int)( 
					( 
					TapArr1_2_h[0][0] *  
					( current_frame[0][jj][ii                   ] 
					+ current_frame[0][jj][Clip(0, maxx, ii + 1)])+ 
					TapArr1_2_h[1][0] * 
					( current_frame[0][jj][Clip(0, maxx, ii - 1)] 
					+ current_frame[0][jj][Clip(0, maxx, ii + 2)])+ 
					TapArr1_2_h[2][0] * 
					( current_frame[0][jj][Clip(0, maxx, ii - 2)] 
					+ current_frame[0][jj][Clip(0, maxx, ii + 3)])+ 
					TapArr1_2_h[3][0] * 
					( current_frame[0][jj][Clip(0, maxx, ii - 3)] 
					+ current_frame[0][jj][Clip(0, maxx, ii + 4)]) 
					+ iWeight1_2_h / 2) 
					>>6 ); 
					 
				//store 1/1 pixel value 
				half_pel_frame_tmp[0][2 * jj][2 * ii]  
					= current_frame[0][jj][Clip(0, maxx, ii)];// 1/1 pix pos 
				//store horizonal 1/2 pixel value 
				half_pel_frame_tmp[0][2 * jj][2 * ii + 1] = Clip(0, 255, val);// 1/2 pix pos 
			} 
		} 
 
  	//vertical 1/2 interpolation 
		maxy = 2 * (pgImage->img_height + 2 * PAD_SIZE) - 2; 
		for (i = 0; i < (pgImage->img_width + 2 * PAD_SIZE) * 2; i++) 
		{ 
			for (j = 0; j < pgImage->img_height + 2 * PAD_SIZE; j++) 
			{	 
				is =(int)( 
					(  
					TapArr1_2_v[0][0] *  
					( half_pel_frame_tmp[0][min(maxy, 2 * j)    ][i] 
					+ half_pel_frame_tmp[0][min(maxy, 2 * j + 2)][i])+ 
					TapArr1_2_v[1][0] * 
					( half_pel_frame_tmp[0][max(0, 2 * j - 2)   ][i] 
					+ half_pel_frame_tmp[0][min(maxy, 2 * j + 4)][i])+ 
					TapArr1_2_v[2][0] * 
					( half_pel_frame_tmp[0][max(0, 2 * j - 4)   ][i] 
					+ half_pel_frame_tmp[0][min(maxy, 2 * j + 6)][i])+ 
					TapArr1_2_v[3][0] * 
					( half_pel_frame_tmp[0][max(0, 2 * j - 6)   ][i] 
					+ half_pel_frame_tmp[0][min(maxy, 2 * j + 8)][i]) 
					+ iWeight1_2_v / 2 )  
					>>3); 
				 
				 
				//vertical half pel 
				yy = min(maxy, 2 * j); 
				reference_half_pel_frame[0][j * 2    ][i] =  Clip(0, 255, half_pel_frame_tmp[0][yy][i]); 
 
				reference_half_pel_frame[0][j * 2 + 1][i] =  Clip(0, 255, is); 
 
				reference_quater_pel_frame[0][4 * j    ][2 * i]  
					= reference_half_pel_frame[0][j * 2][i]; 
				reference_quater_pel_frame[0][4 * j + 2][2 * i]  
					= reference_half_pel_frame[0][j * 2 + 1][i]; 
			} 
		} 
 
		//Quater pel intepolation 
		// 1/4 pix 
		// luma 
		ie2 = (pgImage->img_width  + 2 * PAD_SIZE - 1) * 4; 
		je2 = (pgImage->img_height + 2 * PAD_SIZE - 1) * 4; 
 
		//horizonal 1/4 interpolation 
		for (j = 0; j < je2 + 4; j += 2) 
		{ 
			for (i = 0; i < ie2 + 3; i += 2) 
			{ 
				//  '-' 
				if(i % 4 == 0)  
				{ 
					val = (int) ( 
						( 
						TapArr1_4[0] * reference_quater_pel_frame[0][j][max(0, i - 2)       ] 
						+ TapArr1_4[1] * reference_quater_pel_frame[0][j][i                   ]  
						+ TapArr1_4[2] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] 
						+ TapArr1_4[3] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] 
						+ iWeight1_4 / 2 ) 
						) >>1 ; 
					reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); 
					 
				}else{ 
					val = (int) ( 
						( 
						TapArr1_4[3] * reference_quater_pel_frame[0][j][max(0, i - 2)       ] 
						+ TapArr1_4[2] * reference_quater_pel_frame[0][j][i                   ]  
						+ TapArr1_4[1] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 2)] 
						+ TapArr1_4[0] * reference_quater_pel_frame[0][j][min (ie2 + 2, i + 4)] 
						+ iWeight1_4 / 2 ) 
						) >>1 ; 
					reference_quater_pel_frame[0][j][i + 1] = Clip(0, 255, val); 
				} 
					 
			} 
		} 
		 
  	//vertical 1/4 interpolation 
		for (i = 0; i < ie2 + 4; i++) 
		{ 
			for (j = 0; j < je2 + 3; j += 2) 
			{ 
				// '|' 
				if (i % 2 == 0) 
				{ 
					if(j % 4 == 0) 
					{ 
						val = (int) ( 
							(  
							TapArr1_4[0] * reference_quater_pel_frame[0][max(0, j - 2)      ][i] 
							+ TapArr1_4[1] * reference_quater_pel_frame[0][j                  ][i] 
							+ TapArr1_4[2] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] 
							+ TapArr1_4[3] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] 
							+ iWeight1_4 / 2 )  
							>>1); 
						 
						reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
					}else{ 
						val = (int) ( 
							(  
							TapArr1_4[3] * reference_quater_pel_frame[0][max(0, j - 2)      ][i] 
							+ TapArr1_4[2] * reference_quater_pel_frame[0][j                  ][i] 
							+ TapArr1_4[1] * reference_quater_pel_frame[0][min(je2 + 2, j + 2)][i] 
							+ TapArr1_4[0] * reference_quater_pel_frame[0][min(je2 + 2, j + 4)][i] 
							+ iWeight1_4 / 2 )  
							>>1); 
						 
						reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
					} 
					 
				}			 
				else if (j % 4 == 0 && i % 4 == 1) 
				{ 
					// '\' 
					val = (int) ( 
						( reference_quater_pel_frame[0][j                  ][max(0, i - 1)      ] 
						+ reference_quater_pel_frame[0][min(je2 + 2, j + 2)][min(ie2 + 2, i + 1)]  
						+ 1 ) >>1); 
					reference_quater_pel_frame[0][j + 1][i] =  Clip(0, 255, val); 
				} 
				else if(j % 4 == 2 && i % 4 == 3) 
				{ 
					val = (int) ( 
						( reference_quater_pel_frame[0][j                  ][max(0, i - 1)      ] 
						+ reference_quater_pel_frame[0][min(je2 + 2, j + 2)][min(ie2 + 2, i + 1)] 
						+ 1) >>1); 
					reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
				} 
				else if(j % 4 == 0 && i % 4 == 3) 
				{ 
					//  '/' 
					val = (int) ( 
						( reference_quater_pel_frame[0][j                  ][min(ie2 + 2, i + 1)] 
						+ reference_quater_pel_frame[0][min(je2 + 2, j + 2)][max(0, i - 1)      ] 
						+ 1) >>1); 
					reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
				} 
				else if(j % 4 == 2 && i % 4 == 1) 
				{ 
					//  '/' 
					val = (int) ( 
						( reference_quater_pel_frame[0][j                  ][min(ie2 + 2, i + 1)]  
						+ reference_quater_pel_frame[0][min(je2 + 2, j + 2)][max(0, i - 1)      ] 
						+ 1 ) >>1 ); 
					reference_quater_pel_frame[0][j + 1][i] = Clip(0, 255, val); 
				} 
			}//for (j = 0; j < je2 + 3; j += 2) 
		}//for (i = 0; i < ie2 + 4; i++)	 
}