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; i PicSizeInMbs; 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 }