www.pudn.com > wm2.5.zip > loopfilter.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 "global.h" 
#include "types.h" 
#include "define.h" 
#include "loopfilter.h" 
 
#define _OLD_METHOD_ 
// #define TT1 1    
// #define CC 0      
#define QP_OFset 0  
#define ALPHA_ofset 0  
#define C_OFFSET -1                                                                                                                                              
 
//! make chroma QP from quant 
 
#define  IClip( Min, Max, Val) (((Val)<(Min))? (Min):(((Val)>(Max))? (Max):(Val))) 
 
 
// NOTE: to change the tables below for instance when the QP doubling is changed from 6 to 8 values  
//       send an e-mail to Peter.List@t-systems.com to get a little programm that calculates them automatically  
extern const short QP_SCALE_CR[64]; 
int ALPHA_TABLE[64]  = { 
     0, 0, 0, 0, 0, 0, 1, 1, 
     1, 1, 1, 2, 2, 2, 3, 3, 
     4, 4, 5, 5, 6, 7, 8, 9, 
    10,11,12,13,15,16,18,20, 
    22,24,26,28,30,33,33,35, 
    35,36,37,37,39,39,42,44, 
    46,48,50,52,53,54,55,56, 
    57,58,59,60,61,62,63,64  
} ; 
 
 
 
int CLIP_TAB[64] = { 
  0, 0, 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 1, 1,  
  1, 1, 1, 1, 1, 2, 2, 2, 
  2, 2, 2, 3, 4, 4, 4, 4, 
  5, 5, 5, 5, 5, 6, 6, 6, 
  6, 7, 7, 8, 9, 9, 10,11, 
  12,13,14,15,16,16,16,16 
} ; 
 
 
 
int  ININT_STRENGTH[4] = {0x04040404, 0x03030303, 0x03030303, 0x03030303} ;  
Byte BLK_NUM[2][4][4]  = {{{0,4,8,12},{1,5,9,13},{2,6,10,14},{3,7,11,15}},{{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15}}} ; 
 
 
void  DeblockFrame(Image *img , Byte ***curr_frame) 
{ 
	int       mb_x, mb_y ; 
	int i, j; 
	 
	for (j=0;jimg_height;j++) 
	{ 
		for (i=0;iimg_width;i++) 
		{ 
			imgY_rec[j][i]=curr_frame[0][j+PAD_SIZE][i+PAD_SIZE]; 
		} 
	} 
		for(j=0;jimg_height/2;j++) 
	{ 
		for(i=0;iimg_width/2;i++) 
		{ 
			imgU_rec[j][i]=current_frame[1][j][i]; 
			imgV_rec[j][i]=current_frame[2][j][i]; 
		} 
	} 
 
	for( mb_y=0 ; mb_y<(img->img_height>>4) ; mb_y++ ) 
    for( mb_x=0 ; mb_x<(img->img_width>>4) ; mb_x++ ) 
	{ 
		DeblockMb(img , curr_frame , mb_y , mb_x); 
	} 
	 
    	for (j=0;jimg_height;j++) 
	{ 
		for (i=0;iimg_width;i++) 
		{ 
			current_frame[0][j+PAD_SIZE][i+PAD_SIZE]=imgY_rec[j][i]; 
		} 
	} 
	for(j=0;jimg_height/2;j++) 
	{ 
		for(i=0;iimg_width/2;i++) 
		{ 
			current_frame[1][j][i]=imgU_rec[j][i]; 
			current_frame[2][j][i]=imgV_rec[j][i]; 
		} 
	} 
} 
 
void DeblockMb(Image *img , Byte ***curr_frame , int mb_y , int mb_x) 
{ 
	int           EdgeCondition; 
	int           dir,edge,QP; 
	Byte          *SrcY, *SrcU, *SrcV ; 
	MacroblockHeader    *MbPheader, *MbQheader ;  
	MacroblockData   *MbP , *MbQ; 
	int           QPC; 
	int loopfilter_qp_offset; 
	int alpha_ci_offset; 
	int cp_offset; 
	int threshold; 
	//	WJP FOR SLICE_DEBLOCK 050321 
	int mb_width          = pgImage->img_width/16; 
	int current_mb_nr     = mb_width*mb_y + mb_x; 
    int mb_available_up   = (mb_y == 0) ? 0 :  
							(pgImage->mb_data_forlf[current_mb_nr].slice_nr == pgImage->mb_data_forlf[current_mb_nr-mb_width].slice_nr); 
    int mb_available_left = (mb_x == 0) ? 0 :  
							(pgImage->mb_data_forlf[current_mb_nr].slice_nr == pgImage->mb_data_forlf[current_mb_nr-1].slice_nr); 
 
	if(!pgImage->disable_loop_filter_slice_flag) 
	{ 
		mb_available_up = 1; 
		mb_available_left = 1; 
	} 
	//	WJP END 050321 
	 
	if(active_pps->loop_filter_parameter_flag) 
	{ 
		loopfilter_qp_offset = pgImage->loopfilter_qp_offset; 
		alpha_ci_offset = pgImage->alpha_ci_offset; 
		cp_offset = pgImage->cp_offset; 
	} 
	else 
	{ 
		loopfilter_qp_offset = 0; 
		alpha_ci_offset = 0; 
		cp_offset = 0; 
	} 
 
	SrcY = imgY_rec[mb_y<<4] + (mb_x<<4) ;  
	if (imgUV!=NULL) 
	{ 
		SrcU = imgU_rec[mb_y<<3] + (mb_x<<3) ;   
		SrcV = imgV_rec[mb_y<<3] + (mb_x<<3) ; 
	} 
 
	MbQheader  = &img->mb_headerdata[mb_y*(img->img_width>>4) + mb_x] ; 
	MbQ        = &img->mb_data_forlf[mb_y*(img->img_width>>4) + mb_x ] ; 
	threshold=40 + loopfilter_qp_offset; 
	if (MbQheader->mb_type!=0 || (MbQ->qp_mb>=threshold)) 
	{ 
	  for( dir=0 ; dir<2 ; dir++ )   //1st hor, 2nd ver 
		{ 
		  EdgeCondition = (dir && mb_available_up) || (!dir && mb_available_left);//WJP FOR SLICE_DEBLOCK 050321 
		  for( edge=0 ; edge<4 ; edge++ ) 
			{ 
			  if( edge || EdgeCondition ) 
				{ 
				   MbPheader = (edge)? MbQheader : ((dir)? (MbQheader - (img->img_width>>4)) : (MbQheader-1)); 
				   MbP       = (edge)? MbQ : ((dir)? (MbQ - (img->img_width>>4))  : (MbQ-1) ) ;  
				   QP        = (MbP->qp_mb + MbQ->qp_mb +1)>>1; 
 
//					 if (MbQheader->mb_type==6) 
           if (MbQheader->mb_type==I4MB)  //JX 05-4-1 
					 { 
						EdgeLoop( SrcY + (edge<<2)* ((dir)? img->img_width:1 ), QP, alpha_ci_offset, dir, img->img_width, 0) ; 
						 if(!(edge & 1) ) 
						 { 
							 QPC  =(MbP->qp_mb + MbQ->qp_mb +1)>>1; 
							 EdgeLoop( SrcU +  (edge<<1) * ((dir)? img->img_width>>1:1 ), QPC,  alpha_ci_offset, dir, img->img_width>>1, 1 ) ;  
							 EdgeLoop( SrcV +  (edge<<1) * ((dir)? img->img_width>>1:1 ), QPC,  alpha_ci_offset, dir, img->img_width>>1, 1 ) ;  
						 } 
					 } 
					 else if (!(MbQ->qp_mbmb_type==0))//1230 
					 { 
						EdgeLoopweak( SrcY + (edge<<2)* ((dir)? img->img_width:1 ), QP, alpha_ci_offset, cp_offset, dir, img->img_width, 0) ; 
						 if(!(edge & 1) ) 
						 { 
							 QPC  =(MbP->qp_mb + MbQ->qp_mb +1)>>1; 
							 EdgeLoopweak( SrcU +  (edge<<1) * ((dir)? img->img_width>>1:1 ), QPC,  alpha_ci_offset, cp_offset, dir, img->img_width>>1, 1 ) ;  
							 EdgeLoopweak ( SrcV +  (edge<<1) * ((dir)? img->img_width>>1:1 ), QPC,  alpha_ci_offset, cp_offset, dir, img->img_width>>1, 1 ) ;  
						 } 
					 } 
				    
				} 
			} 
		} 
  } 
} 
 
 
void EdgeLoop(Byte* SrcPtr, int QP, int alpha_ci_offset, int dir,int width,int yuv) 
{ 
  int      pel, ap = 0, aq = 0, PtrInc /*Strng*/ ; 
  int      inc, inc2, inc3, inc4 ; 
  int      Delta, dif, AbsDelta ; 
  int      L2 = 0, L1, L0, L3, R0, R1, R2 = 0, R3 /*RL0*/ ; 
	int      LL,RR;//yf 
	int      dif1; 
  int      Alpha = 0, Beta = 0 ; 
  
  Byte*    ClipTab = NULL, C0;    
   
  PtrInc  = dir?      1 : width ; 
  inc     = dir?  width : 1 ;                     // vertical filtering increment to next pixel is 1 else width 
  inc2    = inc<<1 ;     
  inc3    = inc + inc2 ;     
  inc4    = inc<<2 ; 
   
  
  Alpha=ALPHA_TABLE[IClip(0,63,QP+alpha_ci_offset)];//1230 
  // Beta=BETA_TABLE[QP];   
       
  for( pel=0 ; pel<16 ; pel++ ) 
  { 
 
		L0  = SrcPtr[-inc] ; 
		R0  = SrcPtr[0] ; 
		L1  = SrcPtr[-inc2] ; 
		R1  = SrcPtr[ inc] ; 
		L2  = SrcPtr[-inc3] ; 
		R2  = SrcPtr[ inc2] ; 
		L3  = SrcPtr[-inc4] ; 
		R3  = SrcPtr[ inc3] ; 
		AbsDelta  = abs( Delta = R0 - L0 )  ; 
		LL=abs(L1-L0); 
		RR=abs(R1-R0); 
       
    if( AbsDelta < Alpha) 
    { 
			C0  = CLIP_TAB[ QP ] ; 
			dif = IClip( -C0, C0, ( (R0-L0)*4 + (L1 - R1) + 4) >> 3 ); 
			dif1=dif>>1; 
 
			//left 
			 
			if (L1==L0/*&& !yuv*/)//1230 
			{ 
				SrcPtr[-inc]  = IClip(0, 255, L0 + dif) ;    //l0 
				SrcPtr[-inc2] = IClip(0, 255, L0 + dif1) ;    //l1 
			} 
			else  
			{ 
				SrcPtr[-inc]  = IClip(0, 255, L0 + dif1) ;    //l0 
			} 
 
			//right 
			 
			if (R1==R0 /*&& !yuv*/)//1230 
			{ 
				SrcPtr[0]     = IClip(0, 255, R0 - dif) ;    //r0 
				SrcPtr[ inc]  = IClip(0, 255, R0 - dif1) ;    //r1 
			} 
			else  
			{ 
				SrcPtr[0]     = IClip(0, 255, R0 - dif1) ;    //r0 
			} 
		} 
 
		SrcPtr += PtrInc ;      // Increment to next set of pixel 
		pel    += yuv ;  
  } 
} 
 
 
void EdgeLoopweak(Byte* SrcPtr,int QP, int alpha_ci_offset, int cp_offset, int dir,int width,int yuv) 
{ 
  int      pel, ap = 0, aq = 0, PtrInc /*Strng*/ ; 
  int      inc, inc2, inc3, inc4 ; 
  int      Delta, dif, AbsDelta ; 
  int      L2 = 0, L1, L0, L3, R0, R1, R2 = 0, R3 /*RL0*/ ; 
	int      LL,RR;//yf 
	int      dif1; 
  int      Alpha = 0, Beta = 0 ; 
  
  Byte*    ClipTab = NULL, C0;   
   
  PtrInc  = dir?      1 : width ; 
  inc     = dir?  width : 1 ;                     // vertical filtering increment to next pixel is 1 else width 
  inc2    = inc<<1 ;     
  inc3    = inc + inc2 ;     
  inc4    = inc<<2 ; 
 
   
  Alpha=ALPHA_TABLE[IClip(0,63,QP+alpha_ci_offset)];//1230 
  // Beta=BETA_TABLE[QP];   
	 
  for( pel=0 ; pel<16 ; pel++ ) 
  { 
		L0  = SrcPtr[-inc] ; 
		R0  = SrcPtr[0] ; 
		L1  = SrcPtr[-inc2] ; 
		R1  = SrcPtr[ inc] ; 
		L2  = SrcPtr[-inc3] ; 
		R2  = SrcPtr[ inc2] ; 
		L3  = SrcPtr[-inc4] ; 
		R3  = SrcPtr[ inc3] ; 
		AbsDelta  = abs( Delta = R0 - L0 )  ; 
		LL=abs(L1-L0); 
		RR=abs(R1-R0); 
		 
    if( AbsDelta < Alpha) 
    { 
			//C0  = (CLIP_TAB[ QP ]>>1)+cp_offset;//1230 
			if ((CLIP_TAB[ QP ]>>1)+cp_offset<0) 
				C0=0; 
			else 
			  C0  = (CLIP_TAB[ QP ]>>1)+cp_offset; 
			 
			dif = IClip( -C0, C0, ( (R0-L0)*4 + (L1 - R1) + 4) >> 3 ) ; 
			dif1=dif>>1; 
 
			//left			 
			 
			if (L1==L0 && AbsDelta < (Alpha>>2)+2 )//1230 
			{ 
				SrcPtr[-inc]  = IClip(0, 255, L0 + dif) ;    //l0 
				SrcPtr[-inc2] = IClip(0, 255, L0 + dif1) ;    //l1 
			} 
			else  
			{ 
				SrcPtr[-inc]  = IClip(0, 255, L0 + dif1) ;    //l0 
			} 
 
			//right					 
			 
			if (R1==R0 && AbsDelta < (Alpha>>2)+2 )//1230 
			{ 
				SrcPtr[0]     = IClip(0, 255, R0 - dif) ;    //r0 
				SrcPtr[ inc]  = IClip(0, 255, R0 - dif1) ;    //r1 
				} 
			else  
			{ 
				SrcPtr[0]     = IClip(0, 255, R0 - dif1) ;    //r0 
			} 
		} 
 
		SrcPtr += PtrInc ;      // Increment to next set of pixel 
    pel    += yuv ; 
	} 
}