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


 
/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2004, Advanced Audio Video Coding Standard, Part II 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
 
#include  
#include "global.h" 
#include "interpred.h" 
#include "intrapred.h" 
#include "macroblock.h" 
#include "block.h" 
#include "rdopt.h" 
 
#include "ratectl.h"        // LX 0409                      
extern  MacroblockHeader    MbHeader;      // LX 0409   
 
/* 
************************************************************************* 
* Function:Save RD cost state 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void Save_RD_State() 
{ 
	pgRDStream->bits_to_go = pgcurrBitStream->bits_to_go; 
	pgRDStream->byte_buf = pgcurrBitStream->byte_buf;  
	pgRDStream->byte_pos = pgcurrBitStream->byte_pos; 
} 
 
/* 
************************************************************************* 
* Function:Restore RD cost state 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void Restore_RD_State() 
{ 
    pgcurrBitStream->bits_to_go = pgRDStream->bits_to_go; 
    pgcurrBitStream->byte_buf = pgRDStream->byte_buf; 
    pgcurrBitStream->byte_pos = pgRDStream->byte_pos; 
} 
 
/* 
************************************************************************* 
* Function:Calculate RD cost for a macroblock 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
double RD_Cost_Macrobock() 
{ 
	double distortion; 
	double rdcost; 
	int    rate; 
	int    i, j, uv; 
	int    pic_x =	pgMbData->mb_x<<4; 
	int    pic_y =	pgMbData->mb_y<<4; 
	int    pic_c_x = pic_x>>1; 
	int    pic_c_y = pic_y>>1; 
 
	write_one_macroblock(); 
 
	rate = (pgcurrBitStream->byte_pos - pgRDStream->byte_pos)*8 + (pgRDStream->bits_to_go-pgcurrBitStream->bits_to_go); 
	 
	distortion = 0; 
	for(j=0; j<16; j++) 
	for(i=0; i<16; i++) 
		distortion += quadarr[pgMbData->org_luma[j][i]-imgY[pic_y+j][pic_x+i]]; 
 
	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][pic_c_y+j][pic_c_x+i]]; 
 
	rdcost = distortion + pgMbData->lamda_mode * rate;  
		 
	return rdcost; 
} 
 
/* 
************************************************************************* 
* Function:Calculate RD cost for Inter macroblock 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
int RD_Cost_Inter_Macrobock() 
{ 
	int blocktype; 
	int b8, b4; 
	int i, j, k; 
	int pic_block_x, pic_block_y; 
	int step_h0, step_v0; 
	int img_x = (pgMbData->mb_x<<4); 
	int img_y = (pgMbData->mb_y<<4); 
	int img_c_x = img_x>>1; 
	int img_c_y = img_y>>1; 
	double rdcost, intra_rdcost; 
	int min_cost = 1<<30;//WJP 
	int coeff_cost; 
	int best_mode=1;//WJP 
	int dummy; 
	int old_skip_counter; 
	int best_abt_size, abt_size_flag=0; 
 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
	int iregallow=1; 
	int m,n; 
#endif 
 
	for(blocktype=1; blocktype<=4; blocktype++) 
	{ 
		//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
		iregallow=1; 
		if(input.IREGEnable) 
		{ 
			if(pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) 
			{ 
				for(m=0;m<4;m++) 
				{ 
					for(n=0;n<4;n++) 
					{ 
						if(iIREGReliableFrmFlag==1 || iIREGState==2*input.IREGRate || input.num_reference_frames==1) 
							if(typemap[0][blocktype-1][m][n]==0) 
							{ 
								iregallow=0; 
								break; 
							} 
						else if(typemap[0][blocktype-1][m][n]==0 && typemap[1][blocktype-1][m][n]==0) 
						{ 
							iregallow=0; 
							break; 
						} 
					} 
					if(iregallow==0)break; 
				} 
			} 
			if(iregallow==0) 
			{ 
				rdcost=1<<30; 
				continue; 
			} 
		} 
#endif //_ISOLATED_REGION_ 
		 
		Restore_Motion_Vector(blocktype); 
		 
		//restore reference index 
		for(b8=0; b8<4; b8++) 
		for(b4=0; b4<4; b4++) 
		{ 
			refFrArr[pgImage->block_y+((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] = sInter_Ref[blocktype][b8][b4]; 
		} 
 
		//WJP 040824N 
		if(input.ABT_RDO) 
			abt_size_flag=!abt_size_flag; //qhg for abt 
		else if (blocktype<4) 
		{ 
			abt_size_flag=1; 
		} 
		//WJP 040824N 
		 
		pgMbData->best_mode = blocktype; // P8x8 used when blocktype == 4  
		pgMbHeader->mb_type = blocktype; 
 
		if(pgMbHeader->mb_type == 4)                  //qwang 2004-3-22 
		{ 
			for(i=0; i<4; i++) 
				pgMbHeader->subblk_type[i] = pgMbData->best_mode_subblk[i]; 
			abt_size_flag=0; 
		} 
		 
 
		//--- Set the numbers of MV --- 
		pgMbHeader->mv_num = (pgMbData->best_mode == 3) ? 2 : pgMbData->best_mode; 
		 
		//--- Update left ref --- 
		pgMbData->left_ref = 0; 
		 
		//--- Update Intra line buffer --- 
		for (b8=0;b8<4;b8++) 
		for (b4=0;b4<4;b4++) 
		{ 
			pic_block_x=(img_x/4 + 2*(b8%2)+(b4%2)); 
			pic_block_y=(img_y/4 + 2*(b8/2)+(b4/2)); 
      
      ipredmode[pic_block_x+1][img_y/4+1] = (active_pps->constrained_intra_pred_flag ? -1 : 10);//MZ 
 
 
 /*     if(active_pps->constrained_intra_pred_flag) 
			  c_ipredmode[img_x/16+1][img_y/16+1] = -1;//zhangnan 
      else 
        c_ipredmode[img_x/16+1][img_y/16+1] = 0; //MZ 04-03 
*/ 
		} 
			 
		//--- Get RefIndex info ---   //zhangnan 
		step_h0 = (csiInter_Block_Size[pgMbHeader->mb_type-1][0] >> 2); 
		step_v0 = (csiInter_Block_Size[pgMbHeader->mb_type-1][1] >> 2);  //??? zhangnan 
 
		for (j=0; j<4; j+=step_v0) 
			for (i=0; i<4; i+=step_h0) 
			{ 
				k=j+(i/2); 
				pgMbHeader->refIndex[k] = refFrArr[pgMbData->mb_y*4+j][pgMbData->mb_x*4+i]; 
			} 
				 
		//--- Get MVD info --- 
		for(b8=0; b8<4; b8++) 
			for(b4=0; b4<4; b4++) 
			{ 
				pgMbHeader->mvd[b8][b4][0] = pgMbData->mvb[b8][b4][0] - pgMbData->pred_mv[b8][b4][0]; 
				pgMbHeader->mvd[b8][b4][1] = pgMbData->mvb[b8][b4][1] - pgMbData->pred_mv[b8][b4][1]; 
			} 
				 
		for(b8=0; b8<4; b8++) 
			for(b4=0; b4<4; b4++) 
			{ 
				tmp_mv[0][pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)+4] = pgMbData->mvb[b8][b4][0]; 
				tmp_mv[1][pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)+4] = pgMbData->mvb[b8][b4][1]; 
			} 
				 
		//--- Reset cbp --- 
			pgMbHeader->cbp = 0; 
			// dongjie 
			for(i=0;i<6;i++) 
				pgMbHeader->cbp_4x4[i] = 0; 
			// end 
		Inter_ReLoad_Residual(); 
         
		for (b8=0; b8<4; b8++)      //zhangnan 
		{ 
			coeff_cost = 0; 
			coeff_cost_4x4[0]=coeff_cost_4x4[1]=coeff_cost_4x4[2]=coeff_cost_4x4[3] = 0; // dongjie 
 
			//WJP 040903 
			if(pgMbHeader->mb_type==4 && pgMbHeader->subblk_type[b8]==1 && (!input.ABT_RDO) && input.ABT) 
			{ 
				abt_size_flag=1; 
			} 
			//WJP END 
			 
			if(abt_size_flag==0||!input.ABT) //qhg for abt 
			{ 
				for (b4=0; b4<4; b4++)	 
				{ 
					Transform_B4(b8, b4); 
					 
                    // LX 0409 
					for( i = 0; i < BLOCK_SIZE; i++) 
						for( j = 0; j < BLOCK_SIZE; j++) 
							//  block_x  =  0  4  8  12 
							g_nbestDCTcoef[ b8*4 + i ][ b8*4 + j ]= MbHeader.pred_residual[b8][b4][j][i]; 
                    // LX 0409 
 
					Quant_B4(pgMbData->qp_mb, b8, b4, &coeff_cost); 
				} 
				// dongjie 
				if(pgMbHeader->cbp_4x4[b8]==0) 
					pgMbHeader->cbp &= (~(1<cbp |= (1<qp_mb, b8, &coeff_cost);									 
			} 
			if(coeff_cost <= (b8<4 ? LUMACOEFFCOST:CHROMACOEFFCOST)) 
			{ 
				pgMbHeader->cbp &= (63 - (1<pred_residual[b8][b4][j][i] = 0; 
			} 
			// dongjie 
			else 
			{ 
				for(b4=0;b4<4;b4++) 
				{ 
					if(coeff_cost_4x4[b4] <= LUMACOEFFCOST4x4) 
					{ 
						pgMbHeader->cbp_4x4[b8] &= (15 - (1<pred_residual[b8][b4][j][i] = 0; 
					} 
				} 
			} 
			// end 
			if(abt_size_flag==0||!input.ABT) //qhg for abt 
			{ 
				for (b4=0; b4<4; b4++) 
				{ 
					Dequant_B4(pgMbData->qp_mb, b8, b4);											 
					Inv_Transform_B4(b8, b4); 
				} 
			} 
			else 
			{ 
				abt_dequant_B8(pgMbData->qp_mb,b8); 
				abt_Itransform_B8(b8); 
			} 
			 
			//WJP 040903 
			if(pgMbHeader->mb_type==4 && pgMbHeader->subblk_type[b8]==1 && (!input.ABT_RDO) && input.ABT) 
			{ 
				abt_size_flag=0; 
			} 
			//WJP END			 
		} 
		for(b8=4; b8<6; b8++)  
		{ 
			coeff_cost = 0; 
			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, &coeff_cost);		 
			// dongjie 
			if(pgMbHeader->cbp_4x4[b8]==0) 
				pgMbHeader->cbp &= (~(1<cbp |= (1<cbp &= (63 - (1<pred_residual[b8][b4][j][i] = 0; 
			} 
			// dongjie 
			else 
			{ 
				for(b4=0;b4<4;b4++) 
				{ 
					if(coeff_cost_4x4[b4] <= CHROMACOEFFCOST4x4) 
					{ 
						pgMbHeader->cbp_4x4[b8] &= (15 - (1<pred_residual[b8][b4][j][i] = 0; 
					} 
				} 
			} 
			// end		 
			for(b4=0; b4<4; b4++) 
				Dequant_B4(pgMbData->qp_mb, b8, b4); 
       	//InvTransformChromaDC(b8); 
			for (b4=0; b4<4; b4++)									 
				Inv_Transform_B4(b8, b4);				 
		}		 
		 
		for (b8=0; b8<6; b8++) 
		{ 
			for (b4=0; b4<4; b4++) 
			{ 
				//Inv_Transform_B4(b8, b4); 
				Recon_B4(b8, b4, 1); 
				 
				if(b8<4) 
				{ 
					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];  
					} 
				} 
				else 
				{ 
					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];  
					}	 
				}			 
			} 
		} 
        pgMbHeader->abt_block_size_flag=abt_size_flag; 
		Save_RD_State(); 
		old_skip_counter = pgImage->cod_counter; 
		rdcost = RD_Cost_Macrobock(); 
		pgImage->cod_counter = old_skip_counter; 
		Restore_RD_State(); 
		 	 
		if(rdcost < min_cost) 
		{ 
			best_mode = blocktype; 
			min_cost = (int) rdcost; 
            best_abt_size=abt_size_flag; 
		} 
		if(input.ABT && input.ABT_RDO)//WJP 040824N 
			blocktype=blocktype-abt_size_flag;  //qhg for abt 
	} 
 
	pgMbHeader->mb_type = I4MB; 
	pgMbHeader->cbp = 0;//WJP 040824 
	// dongjie 
	for(i=0;i<6;i++) 
		pgMbHeader->cbp_4x4[i] = 0; 
	// end 
	Intra_Luma_Prediction(&dummy); 
	Intra_Chroma_Prediction(&dummy); 
	 
	Save_RD_State(); 
	intra_rdcost = (int)(4.0*floor(6.0 * pgMbData->lamda_mode + 0.4999)); 
	old_skip_counter = pgImage->cod_counter; 
	intra_rdcost += RD_Cost_Macrobock(); 
	pgImage->cod_counter = old_skip_counter; 
	Restore_RD_State();	 
	 
	Get_Skip_RD_Cost_MB(); 
	 
	//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
    if (input.IREGEnable) 
    { 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] == 1 ) 
        { 
            if (iIntegerPixFlag == 0 || iSubPixFlag1 == 1) 
            { 
                pgMbData->skip_cost = 1 << 30; 
                min_cost = 1 << 30; 
            } 
        } 
		if(typemap[0][0][0][0]==0) 
		{ 
			pgMbData->skip_cost = 1 << 30; 
		} 
        if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] == 2) 
        { 
            pgMbData->skip_cost = 1 << 30; 
            min_cost = 1 << 30; 
        } 
    }//if (input->IREGEnable) 
#endif // _ISOLATED_REGION_ 
	 
 
	if(pgMbData->skip_costskip_costmb_type = 0; 
				  //--- Update Intra line buffer --- 
		  for (b8=0;b8<4;b8++) 
			  for (b4=0;b4<4;b4++) 
			  { 
				  pic_block_x=(img_x/4 + 2*(b8%2)+(b4%2)); 
				  pic_block_y=(img_y/4 + 2*(b8/2)+(b4/2)); 
 
 
          ipredmode[pic_block_x+1][pic_block_y+1] = (active_pps->constrained_intra_pred_flag ? -1:10);//MZ 
 
 
 /*         if(active_pps->constrained_intra_pred_flag) 
				    c_ipredmode[img_x/16 +1][img_y/16+1] = -1;//zhangnan 
          else 
            c_ipredmode[img_x/16 +1][img_y/16+1] = 0; //MZ 04-03-05 
*/ 
 
 
			  } 
         
		write_one_macroblock(); 
		return 0; 
	} 
	else if(intra_rdcost>min_cost) 
	{ 
		Restore_Motion_Vector(best_mode); 
		pgMbData->best_mode = best_mode; 
		pgMbHeader->abt_block_size_flag=best_abt_size; //qhg for abt 
		//restore reference index 
		for(b8=0; b8<4; b8++) 
			for(b4=0; b4<4; b4++) 
			{ 
				refFrArr[pgImage->block_y+((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] = sInter_Ref[best_mode][b8][b4]; 
			} 
			 
		return 1; 
	} 
	else//INTRA-coded 
	{ 
	 
		pgMbHeader->mb_type = I4MB; 
		pgMbHeader->cbp = 0;//WJP 040824 
		// dongjie 
		for(i=0;i<6;i++) 
			pgMbHeader->cbp_4x4[i] = 0; 
		// end 
		Intra_Luma_Prediction(&dummy); 
		Intra_Chroma_Prediction(&dummy); 
		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; 
			} 
			 
		write_one_macroblock(); 
 
#ifdef _ISOLATED_REGION_ 
		if(input.IREGEnable) 
		{ 
			intrambcount++; 
		} 
#endif 
		return 0; 
	} 
  
} 
 
/* 
************************************************************************* 
* Function:Calculate SA(T)D 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
int SATD (int* diff) 
{ 
  int k, satd = 0, m[16], dd, *d=diff; 
   
 
    /*===== hadamard transform =====*/ 
    m[ 0] = d[ 0] + d[12]; 
    m[ 4] = d[ 4] + d[ 8]; 
    m[ 8] = d[ 4] - d[ 8]; 
    m[12] = d[ 0] - d[12]; 
    m[ 1] = d[ 1] + d[13]; 
    m[ 5] = d[ 5] + d[ 9]; 
    m[ 9] = d[ 5] - d[ 9]; 
    m[13] = d[ 1] - d[13]; 
    m[ 2] = d[ 2] + d[14]; 
    m[ 6] = d[ 6] + d[10]; 
    m[10] = d[ 6] - d[10]; 
    m[14] = d[ 2] - d[14]; 
    m[ 3] = d[ 3] + d[15]; 
    m[ 7] = d[ 7] + d[11]; 
    m[11] = d[ 7] - d[11]; 
    m[15] = d[ 3] - d[15]; 
     
    d[ 0] = m[ 0] + m[ 4]; 
    d[ 8] = m[ 0] - m[ 4]; 
    d[ 4] = m[ 8] + m[12]; 
    d[12] = m[12] - m[ 8]; 
    d[ 1] = m[ 1] + m[ 5]; 
    d[ 9] = m[ 1] - m[ 5]; 
    d[ 5] = m[ 9] + m[13]; 
    d[13] = m[13] - m[ 9]; 
    d[ 2] = m[ 2] + m[ 6]; 
    d[10] = m[ 2] - m[ 6]; 
    d[ 6] = m[10] + m[14]; 
    d[14] = m[14] - m[10]; 
    d[ 3] = m[ 3] + m[ 7]; 
    d[11] = m[ 3] - m[ 7]; 
    d[ 7] = m[11] + m[15]; 
    d[15] = m[15] - m[11]; 
     
    m[ 0] = d[ 0] + d[ 3]; 
    m[ 1] = d[ 1] + d[ 2]; 
    m[ 2] = d[ 1] - d[ 2]; 
    m[ 3] = d[ 0] - d[ 3]; 
    m[ 4] = d[ 4] + d[ 7]; 
    m[ 5] = d[ 5] + d[ 6]; 
    m[ 6] = d[ 5] - d[ 6]; 
    m[ 7] = d[ 4] - d[ 7]; 
    m[ 8] = d[ 8] + d[11]; 
    m[ 9] = d[ 9] + d[10]; 
    m[10] = d[ 9] - d[10]; 
    m[11] = d[ 8] - d[11]; 
    m[12] = d[12] + d[15]; 
    m[13] = d[13] + d[14]; 
    m[14] = d[13] - d[14]; 
    m[15] = d[12] - d[15]; 
     
    d[ 0] = m[ 0] + m[ 1]; 
    d[ 1] = m[ 0] - m[ 1]; 
    d[ 2] = m[ 2] + m[ 3]; 
    d[ 3] = m[ 3] - m[ 2]; 
    d[ 4] = m[ 4] + m[ 5]; 
    d[ 5] = m[ 4] - m[ 5]; 
    d[ 6] = m[ 6] + m[ 7]; 
    d[ 7] = m[ 7] - m[ 6]; 
    d[ 8] = m[ 8] + m[ 9]; 
    d[ 9] = m[ 8] - m[ 9]; 
    d[10] = m[10] + m[11]; 
    d[11] = m[11] - m[10]; 
    d[12] = m[12] + m[13]; 
    d[13] = m[12] - m[13]; 
    d[14] = m[14] + m[15]; 
    d[15] = m[15] - m[14]; 
     
    /*===== sum up =====*/ 
    for (dd=diff[k=0]; k<16; dd=diff[++k]) 
    { 
      satd += (dd < 0 ? -dd : dd); 
    } 
    satd >>= 1; 
   
  return satd; 
}