www.pudn.com > jm74.zip > loopFilter.c.new


 
/*! 
 ************************************************************************************* 
 * \file loopFilter.c 
 * 
 * \brief 
 *    Filter to reduce blocking artifacts on a macroblock level. 
 *    The filter strengh is QP dependent. 
 * 
 * \author 
 *    Contributors: 
 *    - Peter List       Peter.List@t-systems.de:  Original code                                 (13-Aug-2001) 
 *    - Jani Lainema     Jani.Lainema@nokia.com:   Some bug fixing, removal of recusiveness      (16-Aug-2001) 
 *    - Peter List       Peter.List@t-systems.de:  inplace filtering and various simplifications (10-Jan-2002) 
 *    - Anthony Joch     anthony@ubvideo.com:      Simplified switching between filters and  
 *                                                 non-recursive default filter.                 (08-Jul-2002) 
 *    - Cristina Gomila  cristina.gomila@thomson.net: Simplification of the chroma deblocking 
 *                                                    from JVT-E089                              (21-Nov-2002) 
 ************************************************************************************* 
 */ 
#include  
#include  
#include "global.h" 
#include "image.h" 
#include "mb_access.h" 
 
extern const byte QP_SCALE_CR[52] ; 
 
/*********************************************************************************************************/ 
 
// 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  
 
byte ALPHA_TABLE[52]  = {0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,4,4,5,6,  7,8,9,10,12,13,15,17,  20,22,25,28,32,36,40,45,  50,56,63,71,80,90,101,113,  127,144,162,182,203,226,255,255} ; 
byte  BETA_TABLE[52]  = {0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,2,2,2,3,  3,3,3, 4, 4, 4, 6, 6,   7, 7, 8, 8, 9, 9,10,10,  11,11,12,12,13,13, 14, 14,   15, 15, 16, 16, 17, 17, 18, 18} ; 
byte CLIP_TAB[52][5]  = 
{ 
  { 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0}, 
  { 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0}, 
  { 0, 0, 0, 0, 0},{ 0, 0, 0, 1, 1},{ 0, 0, 0, 1, 1},{ 0, 0, 0, 1, 1},{ 0, 0, 0, 1, 1},{ 0, 0, 1, 1, 1},{ 0, 0, 1, 1, 1},{ 0, 1, 1, 1, 1}, 
  { 0, 1, 1, 1, 1},{ 0, 1, 1, 1, 1},{ 0, 1, 1, 1, 1},{ 0, 1, 1, 2, 2},{ 0, 1, 1, 2, 2},{ 0, 1, 1, 2, 2},{ 0, 1, 1, 2, 2},{ 0, 1, 2, 3, 3}, 
  { 0, 1, 2, 3, 3},{ 0, 2, 2, 3, 3},{ 0, 2, 2, 4, 4},{ 0, 2, 3, 4, 4},{ 0, 2, 3, 4, 4},{ 0, 3, 3, 5, 5},{ 0, 3, 4, 6, 6},{ 0, 3, 4, 6, 6}, 
  { 0, 4, 5, 7, 7},{ 0, 4, 5, 8, 8},{ 0, 4, 6, 9, 9},{ 0, 5, 7,10,10},{ 0, 6, 8,11,11},{ 0, 6, 8,13,13},{ 0, 7,10,14,14},{ 0, 8,11,16,16}, 
  { 0, 9,12,18,18},{ 0,10,13,20,20},{ 0,11,15,23,23},{ 0,13,17,25,25} 
} ; 
 
 
 
void GetStrength(byte Strength[16],struct img_par *img,Macroblock* MbP[16],Macroblock* MbQ[16],int dir,int edge,int mb_y,int mb_x, int mvlimit); 
void EdgeLoop(byte* SrcPtr,byte Strength[16], int QP[16], int AlphaC0Offset, int BetaOffset, int dir,int width,int yuv); 
void DeblockMb(ImageParameters *img, byte **imgY, byte ***imgUV, int mbaddr) ; 
 
/*! 
 ***************************************************************************************** 
 * \brief 
 *    Filter all macroblocks in order of increasing macroblock address. 
 ***************************************************************************************** 
 */ 
void DeblockFrame(ImageParameters *img, byte **imgY, byte ***imgUV) 
{ 
  unsigned i; 
 
  for (i=0; iPicSizeInMbs; i++) 
    DeblockMb( img, imgY, imgUV, i ) ; 
}  
 
 
/*! 
 ***************************************************************************************** 
 * \brief 
 *    Deblocking filter for one macroblock. 
 ***************************************************************************************** 
 */ 
 
void DeblockMb(ImageParameters *img, byte **imgY, byte ***imgUV, int mb_addr) 
{ 
  int           EdgeCondition; 
  int           edge; //,dir; 
  byte          Strength[16],*SrcY, *SrcU, *SrcV ; 
  Macroblock    *MbQ[16], *MbP[16], *MbP_temp;  
  int           QPC[16],QP[16]; 
  int           mb_x, mb_y; 
   
  int           filterLeftMbEdgeFlag; 
  int           filterTopMbEdgeFlag; 
  int           fieldModeMbFlag; 
  int           mvlimit=4; 
  int			      horizontal;  //replaced dir 
  int           i; 
  int           qPp,qPq; 
   
  get_mb_block_pos(mb_addr, &mb_x, &mb_y); 
   
  filterLeftMbEdgeFlag  = (mb_x != 0); 
  filterTopMbEdgeFlag   = (mb_y != 0); 
   
  SrcY = imgY    [mb_y<<4] + (mb_x<<4) ;                     // pointers to source 
  SrcU = imgUV[0][mb_y<<3] + (mb_x<<3) ; 
  SrcV = imgUV[1][mb_y<<3] + (mb_x<<3) ; 
   
  for (i=0; i<16; i++) 
  { 
    MbQ[i] = ( img->mb_data[mb_addr].mb_field ?  
               &img->mb_data[(mb_addr & ~1) + (i%2)] :  
               &img->mb_data[mb_addr]) ;                            // current Mb 
  } 
   
  fieldModeMbFlag = img->field_pic_flag || (img->MbaffFrameFlag && MbQ[0]->mb_field); 
 
  if (fieldModeMbFlag) 
    mvlimit = 2; 
   
  // return, if filter is disabled 
  if (img->mb_data[mb_addr].LFDisableIdc==1) return; 
   
  if (img->mb_data[mb_addr].LFDisableIdc==2) 
  { 
    // don't filter at slice boundaries 
    filterLeftMbEdgeFlag = img->mb_data[mb_addr].mbAvailA; 
    filterTopMbEdgeFlag  = img->mb_data[mb_addr].mbAvailB; 
  } 
 
  for( horizontal=0 ; horizontal<2 ; horizontal++ )         // vertical edges, then horizontal edges 
  { 
    // cannot filter beyond picture boundaries (or slice boundaries if LFDisableIdc == 2) 
    EdgeCondition = (horizontal && filterTopMbEdgeFlag) || (!horizontal && filterLeftMbEdgeFlag);  
 
    for( edge=0 ; edge<4 ; edge++ )                        // first 4 vertical strips of 16 pel 
    {                                                      // then  4 horizontal 
      if( edge || EdgeCondition ) 
      { 
        // [*]Getting Remote MB data: MbPa & MbPb --------------------------------------------------------------------------------- 
        // Figure out what macroblock(s) are on the other side of this edge */ 
 
        if (img->MbaffFrameFlag)  
        { 
          if(edge)  
          { // interior edge  
            for (i=0; i<16; i++)  
              MbP[i] = MbQ[i];                   //interior edge means all blocks are within curMB 
          } 
          else if (!horizontal)  
          { // left MB edge  
            if(img->mb_data[mb_addr].mb_field)   
            {                                                    // current is field 
              if( img->mb_data[mb_addr-2].mb_field )                            //   remote is field 
              { 
                for (i=0; i<16; i++)  
                  MbP[i] = &img->mb_data[mb_addr - 2]; 
              } 
              else                                               //   remote is frame 
              { 
                for (i=0; i<8; i++)  
                { 
                  MbP[i]   = &img->mb_data[(mb_addr & ~1) - 2];  // to apply to top half 
                  MbP[i+8] = &img->mb_data[(mb_addr & ~1) - 1];  // to apply to bottom half 
                } 
              } 
            } 
            else  
            {                                                    // current is frame 
              if(img->mb_data[mb_addr-2].mb_field)  
              {                                                  //   remote is field 
                for (i=0; i<16; i+=2)  
                { 
                  MbP[i]   = &img->mb_data[(mb_addr & ~1) - 2];    // to apply to top field lines 
                  MbP[i+1] = &img->mb_data[(mb_addr & ~1) - 1];	   // to apply to bot field lines 
                } 
              }  
              else  
              {                                                  // remote is frame 
                for (i=0; i<16; i++)  
                  MbP[i] = &img->mb_data[mb_addr - 2]; 
              } 
            } 
          } 
          else  
          { // top MB edge  
            if(img->mb_data[mb_addr].mb_field)  
            {                                                                  // current is field 
              if( img->mb_data[mb_addr - (img->PicWidthInMbs << 1) ].mb_field )               //   remote is field 
              { 
                for (i=0; i<16; i++) 
                  MbP[i] = &img->mb_data[mb_addr - (img->PicWidthInMbs << 1)];                          
              } 
              else                                                             //   remote is frame 
              { 
                for (i=0; i<16; i++)  
                  MbP[i] = &img->mb_data[(mb_addr | 1) - (img->PicWidthInMbs << 1)]; 
              } 
            } 
            else  
            {                                                                 // current is frame 
              if(mb_addr & 1)  
              {                                                               // remote is topMB in same MB pair 
                for (i=0; i<16; i++)  
                  MbP[i] = &img->mb_data[mb_addr - 1]; 
              } 
              else  
              { 
                if( img->mb_data[mb_addr - (img->PicWidthInMbs << 1) ].mb_field ) 
                {        // remote is field 
                  for (i=0; i<16; i++)  
                    MbP[i] = &img->mb_data[(mb_addr & ~1) - (img->PicWidthInMbs << 1)]; // to apply to top field lines 
                }  
                else 
                {                                                                                                          // remote is frame 
                  for (i=0; i<16; i++)  
                    MbP[i] = &img->mb_data[(mb_addr | 1) - (img->PicWidthInMbs << 1)]; 
                } 
              } 
            } 
          } 
        } //End of MBAFF = 1 
        else  
        { 
          // MbP = Left or Upper Mb  
          MbP_temp = (edge)? &img->mb_data[mb_addr] : ((horizontal)? &img->mb_data[mb_addr - img->PicWidthInMbs]  : &img->mb_data[mb_addr-1] ) ;        
          for (i=0; i<16; i++)  
            MbP[i] = MbP_temp; 
           
        } //End of MBAFF = 0 
         
        // GJS: The rest of this needs work 
         
        // As in Draft, if MB is I_PCM, MB->qp should be 0 or corresponding value of 0 for chroma 
        // This is set in decode_ipcm_mb() and here affect the values of QP and QPC (QP_SCALE_CR[]) 
         
        // [*] PARAMETER SETUP: AVERAGE QP & Bs (Boundary Strength) ------------------------------------------------------ 
        // Average QP of the two blocks 
        //QP is for chroma flag = 0 (yuv) 
         
        for(i=0; i<16; i++) 
        { 
          qPp    = ((MbP[i]->mb_type == IPCM) ? 0 : MbP[i]->qp);   // IPCM = 14 at defines.h 
          qPq    = ((MbQ[i]->mb_type == IPCM) ? 0 : MbQ[i]->qp); 
          QP[i]  = ( qPp + qPq + 1) >> 1;                          // Average QP of the two blocks 
        } 
         
        //Need work for GetStrength(): MbP --> MbP[i]  
        GetStrength( Strength, img, MbP, MbQ, horizontal, edge, mb_y<<2, mb_x<<2, mvlimit); // Strength for 4 blks in 1 stripe 
  
        //Need more work done below 
         
        if( *((int*)Strength) )                      // only if one of the 4 Strength bytes is != 0 
        { 
          EdgeLoop( SrcY + (edge<<2)* ((horizontal)? img->width:1 ), Strength, QP, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width, 0) ;  
           
          if( (imgUV != NULL) && !(edge & 1) ) 
          { 
            //8.7.2.2 (chroma flag = 1) 
            for(i=0; i<16; i++)  
            { 
              qPq = MbQ[i]->mb_type==IPCM ? QP_SCALE_CR[0] : QP_SCALE_CR[MbQ[i]->qp]; 
              qPp = MbP[i]->mb_type==IPCM ? QP_SCALE_CR[0] : QP_SCALE_CR[MbP[i]->qp]; 
              QPC[i] = (qPp + qPq + 1) >> 1;								 
            } 
             
            EdgeLoop( SrcU +  (edge<<1) * ((horizontal)? img->width_cr:1 ), Strength, QPC, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width_cr, 1 ) ;  
            EdgeLoop( SrcV +  (edge<<1) * ((horizontal)? img->width_cr:1 ), Strength, QPC, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width_cr, 1 ) ;  
          } 
        } 
         
        // In the strangest case, filter again for the top edge of the bottom field  
        if(img->MbaffFrameFlag && !edge && horizontal && !MbQ[0]->mb_field && !(mb_addr & 1) &&  
          img->mb_data[mb_addr - (img->PicWidthInMbs << 1)].mb_field) 
        { 
          for(i=0; i<16; i++)  
          { 
            MbP[i] = &img->mb_data[(mb_addr | 1) - (img->PicWidthInMbs << 1)]; // to apply to bot field lines 
             
            // In the second pass, we don't need to compute Average QP of the two blocks again. 
          } 
           
          GetStrength(Strength,img,MbP,MbQ,horizontal,edge,mb_y<<2,mb_x<<2, mvlimit); // Strength for 4 blks in 1 stripe 
           
          if( *((int*)Strength) )                      // only if one of the 4 Strength bytes is != 0 
          { 
            EdgeLoop( SrcY + (edge<<2)* ((horizontal)? img->width:1 ), Strength, QP, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width, 0) ;  
             
            if( (imgUV != NULL) && !(edge & 1) ) 
            { 
              EdgeLoop( SrcU +  (edge<<1) * ((horizontal)? img->width_cr:1 ), Strength, QPC, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width_cr, 1 ) ;  
              EdgeLoop( SrcV +  (edge<<1) * ((horizontal)? img->width_cr:1 ), Strength, QPC, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width_cr, 1 ) ;  
            }  
          } 
        }//end strangest case		 
      }//end edge condition 
    }//end edge 
  }//end loop horizontal 
} 
 
  /*! 
 ********************************************************************************************* 
 * \brief 
 *    returns a buffer of 4 Strength values for one stripe in a mb (for different Frame types) 
 ********************************************************************************************* 
 */ 
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}}} ; 
byte BLK_4_TO_8[16]    = {0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3} ; 
 
void GetStrength(byte Strength[16],struct img_par *img,Macroblock* MbP[16],Macroblock* MbQ[16],int dir,int edge,int block_y,int block_x, int mvlimit) 
{ 
  int    blkP, blkQ, idx ; 
  int    blk_x, blk_x2, blk_y, blk_y2 ; 
  int    ***list0_mv = dec_picture->mv[LIST_0]; 
  int    ***list1_mv = dec_picture->mv[LIST_1]; 
  int    **list0_refIdxArr = dec_picture->ref_idx[LIST_0]; 
  int    **list1_refIdxArr = dec_picture->ref_idx[LIST_1]; 
  int    **list0_refPicIdArr = dec_picture->ref_pic_id[LIST_0]; 
  int    **list1_refPicIdArr = dec_picture->ref_pic_id[LIST_1]; 
 
  int i; 
  int mixedModeEdgeFlag[16]; 
  int inIntraPrediction = 0;   
  int FrameMbs          = 0;   
 
  for(i = 0;i<16;i++) 
  { 
	  mixedModeEdgeFlag[i] = img->MbaffFrameFlag ? (MbP[i]->mb_field != MbQ[i]->mb_field) : 0; //8.7.2.1 
  } 
 
  for( idx=0 ; idx<16 ; idx++ ) 
  { 
    Strength[idx] = initStrength; 
  } 
 
  for( idx=0 ; idx<16 ; idx++ ) 
  {                                                
    blkQ = BLK_NUM[dir][ edge       ][idx<<2]; 
    blkP = BLK_NUM[dir][(edge-1) & 3][idx<<2];  
 
    inIntraPrediction = (MbP[idx]->mb_type==I4MB || MbP[idx]->mb_type==I16MB || MbP[idx]->mb_type==IPCM) || (MbQ[idx]->mb_type==I4MB || MbQ[idx]->mb_type==I16MB || MbQ[idx]->mb_type==IPCM); 
    FrameMbs          = (img->structure==FRAME) || (img->MbaffFrameFlag && (!MbP[idx]->mb_field) (!MbQ[idx]->mb_field)); 
 
    // check for bS=4 
    if ((!edge) && inIntraPrediction && (FrameMbs || (!dir && ((img->structure!=FRAME) || img->MbaffFrameFlag))) ) 
    { 
      Strength[idx] = 4; 
    } 
    else 
    { 
      // check for bS = 3 
      if(((!mixedModeEdgeFlag[idx]) && inIntraPrediction)||(mixedModeEdgeFlag[idx] && dir && inIntraPrediction)) 
      { 
        Strength[idx] = 3; 
      } 
      else 
      { 
        // check for bS = 2 
        if( ((MbQ->cbp_blk &  (1 << blkQ )) != 0) || ((MbP[idx]->cbp_blk &  (1 << blkP)) != 0) ) 
        { 
          Strength[idx] = 2; 
        } 
        else 
        { 
          // check for bS = 1 
          if (mixedModeEdgeFlag[idx]) 
          { 
            Strength[idx] = 1; 
          } 
          else 
          { 
            Strength[idx] = 0; 
            if () 
 
          } 
 
 
        } 
 
      } 
    } 
 
    { // do things normally 
        else 
        {                                                     // if no coefs, but vector difference >= 1 set Strength=1  
          blk_y  = block_y + (blkQ >> 2) ;   blk_y2 = blk_y -  dir ; 
          blk_x  = block_x + (blkQ  & 3) ;   blk_x2 = blk_x - !dir ; 
          if( (img->type == B_SLICE) ) 
          {  
            int ref_p0,ref_p1,ref_q0,ref_q1;	     
            ref_p0 = list0_refIdxArr[blk_x][blk_y]<0 ? -1 : list0_refPicIdArr[blk_x][blk_y]; 
            ref_q0 = list0_refIdxArr[blk_x2][blk_y2]<0 ? -1 : list0_refPicIdArr[blk_x2][blk_y2]; 
            ref_p1 = list1_refIdxArr[blk_x][blk_y]<0 ? -1 : list1_refPicIdArr[blk_x][blk_y]; 
            ref_q1 = list1_refIdxArr[blk_x2][blk_y2]<0 ? -1 : list1_refPicIdArr[blk_x2][blk_y2]; 
            if ( ((ref_p0==ref_q0) && (ref_p1==ref_q1)) || 
              ((ref_p0==ref_q1) && (ref_p1==ref_q0)))  
            { 
              Strength[idx]=0; 
              // L0 and L1 reference pictures of p0 are different; q0 as well 
              if (ref_p0 != ref_p1)  
              {	 
                // compare MV for the same reference picture 
                if (ref_p0==ref_q0)  
                { 
                  Strength[idx] =  (abs( list0_mv[blk_x][blk_y][0] - list0_mv[blk_x2][blk_y2][0]) >= 4) | 
                    (abs( list0_mv[blk_x][blk_y][1] - list0_mv[blk_x2][blk_y2][1]) >= mvlimit) | 
                    (abs( list1_mv[blk_x][blk_y][0] - list1_mv[blk_x2][blk_y2][0]) >= 4) | 
                    (abs( list1_mv[blk_x][blk_y][1] - list1_mv[blk_x2][blk_y2][1]) >= mvlimit); 
                } 
                else  
                { 
                  Strength[idx] =  (abs( list0_mv[blk_x][blk_y][0] - list1_mv[blk_x2][blk_y2][0]) >= 4) | 
                    (abs( list0_mv[blk_x][blk_y][1] - list1_mv[blk_x2][blk_y2][1]) >= mvlimit) | 
                    (abs( list1_mv[blk_x][blk_y][0] - list0_mv[blk_x2][blk_y2][0]) >= 4) | 
                    (abs( list1_mv[blk_x][blk_y][1] - list0_mv[blk_x2][blk_y2][1]) >= mvlimit); 
                }	 
              }  
              else  
              { 	// L0 and L1 reference pictures of p0 are the same; q0 as well 
                 
                Strength[idx] =  ((abs( list0_mv[blk_x][blk_y][0] - list0_mv[blk_x2][blk_y2][0]) >= 4) | 
                  (abs( list0_mv[blk_x][blk_y][1] - list0_mv[blk_x2][blk_y2][1]) >= mvlimit ) | 
                  (abs( list1_mv[blk_x][blk_y][0] - list1_mv[blk_x2][blk_y2][0]) >= 4) | 
                  (abs( list1_mv[blk_x][blk_y][1] - list1_mv[blk_x2][blk_y2][1]) >= mvlimit)) 
                  && 
                  ((abs( list0_mv[blk_x][blk_y][0] - list1_mv[blk_x2][blk_y2][0]) >= 4) | 
                  (abs( list0_mv[blk_x][blk_y][1] - list1_mv[blk_x2][blk_y2][1]) >= mvlimit) | 
                  (abs( list1_mv[blk_x][blk_y][0] - list0_mv[blk_x2][blk_y2][0]) >= 4) | 
                  (abs( list1_mv[blk_x][blk_y][1] - list0_mv[blk_x2][blk_y2][1]) >= mvlimit)); 
              }  
            } 
            else  
            { 
              Strength[idx] = 1;				 
            }		 
          }  
          else	 
          { 	// P slice 
            int ref_p0,ref_q0;	     
            ref_p0 = list0_refIdxArr[blk_x][blk_y]<0 ? -1 : list0_refPicIdArr[blk_x][blk_y]; 
            ref_q0 = list0_refIdxArr[blk_x2][blk_y2]<0 ? -1 : list0_refPicIdArr[blk_x2][blk_y2]; 
            Strength[idx] =  (ref_p0 != ref_q0 ) | 
              (abs( list0_mv[blk_x][blk_y][0] - list0_mv[blk_x2][blk_y2][0]) >= 4 ) | 
              (abs( list0_mv[blk_x][blk_y][1] - list0_mv[blk_x2][blk_y2][1]) >= mvlimit ); 
          } 
        }  
      } 
    } 
  } 
} 
 
 
/*! 
 ***************************************************************************************** 
 * \brief 
 *    Filters one edge of 16 (luma) or 8 (chroma) pel 
 ***************************************************************************************** 
 */ 
void EdgeLoop(byte* SrcPtr, byte Strength[16],int QP[16], 
              int AlphaC0Offset, int BetaOffset, int dir, int width, int yuv) 
{  //8.7.1 
  int      pel, ap = 0, aq = 0, PtrInc, Strng ; 
  int      inc, inc2, inc3, inc4 ; 
  int      C0, c0, Delta, dif, AbsDelta ; 
  int      L2 = 0, L1, L0, R0, R1, R2 = 0, RL0 ; 
  int      Alpha[16], Beta[16]; 
  byte*  ClipTab[16]; 
  int      small_gap; 
  int      indexA, indexB; 
 
  //PrtInc/inc used to handle 8-320 -> 327  
  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 ; 
 
  for( pel=0 ; pel<16 ; pel++ ) 
  { 
	  //8.7.2.2 outputs here - indexA, indexB, Alpha, Beta.   
      indexA = Clip3(0, MAX_QP, QP[pel] + AlphaC0Offset);   
      indexB = Clip3(0, MAX_QP, QP[pel] + BetaOffset);   
       
	  Alpha[pel] = ALPHA_TABLE[indexA]; 
	  Beta[pel] = BETA_TABLE[indexB]; 
	  ClipTab[pel]=CLIP_TAB[indexA]; 
	   
      if( (Strng = Strength[pel]) )  //filterSamplesFlag (8-333 equaliviant) 
	  { 
		  L0  = SrcPtr [-inc ] ; 
          R0  = SrcPtr [    0] ; 
          AbsDelta  = abs( Delta = R0 - L0 )  ; 
      
	      if( AbsDelta < Alpha[pel] ) 
		  { 
			  C0  = ClipTab[pel][ Strng ] ; 
		      L1  = SrcPtr[-inc2] ; 
		      R1  = SrcPtr[ inc ] ; 
		      if( ((abs( R0 - R1) - Beta[pel] )  & (abs(L0 - L1) - Beta[pel] )) < 0  )  
			  { 
				  if( !yuv)   
				  { 
					  L2  = SrcPtr[-inc3] ; 
			          R2  = SrcPtr[ inc2] ; 
			          aq  = (abs( R0 - R2) - Beta[pel] ) < 0  ;  
			          ap  = (abs( L0 - L2) - Beta[pel] ) < 0  ;  
				  } 
           
				  RL0             = L0 + R0 ; 
          			 
				  if(Strng == 4 )    // INTRA strong filtering 8.7.2.4 
				  { 
					  if( yuv)  // Chroma 
					  { 
						  SrcPtr[   0 ] = ((R1 << 1) + R0 + L1 + 2) >> 2; //8-351 
			              SrcPtr[-inc ] = ((L1 << 1) + L0 + R1 + 2) >> 2; //8-358                                    
					  } 
			          else  // Luma 
					  {  
						  small_gap = (AbsDelta < ((Alpha[pel] >> 2) + 2)); 
                 
				          aq &= small_gap;  //8-347 
				          ap &= small_gap;  //8-354 
               
			              SrcPtr[   0 ]   = aq ? ( L1 + ((R1 + RL0) << 1) +  SrcPtr[ inc2] + 4) >> 3 : ((R1 << 1) + R0 + L1 + 2) >> 2 ;  //8-348, 8-351 
				          SrcPtr[-inc ]   = ap ? ( R1 + ((L1 + RL0) << 1) +  SrcPtr[-inc3] + 4) >> 3 : ((L1 << 1) + L0 + R1 + 2) >> 2 ;  //8-355, 8-358 
               
				          SrcPtr[ inc ] =   aq  ? ( SrcPtr[ inc2] + R0 + R1 + L0 + 2) >> 2 : SrcPtr[ inc ];  //8-349, 8-352 
				          SrcPtr[-inc2] =   ap  ? ( SrcPtr[-inc3] + L1 + L0 + R0 + 2) >> 2 : SrcPtr[-inc2];  //8-346, 8-359 
               
				          SrcPtr[ inc2] = aq ? (((SrcPtr[ inc3] + SrcPtr[ inc2]) <<1) + SrcPtr[ inc2] + R1 + RL0 + 4) >> 3 : R2;  //8-350, 8-353 
				          SrcPtr[-inc3] = ap ? (((SrcPtr[-inc4] + SrcPtr[-inc3]) <<1) + SrcPtr[-inc3] + L1 + RL0 + 4) >> 3 : L2;  //8-357, 8-360 
					  } 
				  } 
			      else                        // normal filtering 8.7.2.3 
				  { 
			              c0               = yuv? (C0+1):(C0 + ap + aq) ;  //8-337, 8-338 
			              dif              = Clip3( -c0, c0, ( (Delta << 2) + (L1 - R1) + 4) >> 3 ) ;  //8-334 
			              SrcPtr[  -inc ]  = Clip3(0, 255, L0 + dif) ; 
			              SrcPtr[     0 ]  = Clip3(0, 255, R0 - dif) ; 
             
		             	  if( !yuv ) 
						  { 
							  if( ap ) 
								  SrcPtr[-inc2] += Clip3( -C0,  C0, ( L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1 ) ; 
							  if( aq  )   
								  SrcPtr[  inc] += Clip3( -C0,  C0, ( R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1 ) ; 
						  } ; 
				  } ; 
			  } ;  
		  } ; 
	   
          SrcPtr += PtrInc ;      // Increment to next set of pixel 
          pel    += yuv ; 
	  }  
      else 
	  { 
		  SrcPtr += PtrInc << (2 - yuv) ; 
          pel    += 3 ; 
	  }  ; 
   
  }//end of FOR 
 
}