📄 loopfilter.c
字号:
/*!
*************************************************************************************
* \file loopFilter.c
*
* \brief
* Filter to reduce blocking artifacts on a macroblock level.
* The filter strength 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 recursiveness (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)
* - Alexis Michael Tourapis atour@dolby.com: Speed/Architecture improvements (08-Feb-2007)
*************************************************************************************
*/
#include "global.h"
#include "image.h"
#include "mb_access.h"
#include "loopfilter.h"
byte mixedModeEdgeFlag, fieldModeFilteringFlag;
static int64 **list0_refPicIdArr, **list1_refPicIdArr;
static short ***list0_mv, ***list1_mv;
static char **list0_refIdxArr, **list1_refIdxArr;
static Macroblock *MbP;
static imgpel *SrcPtrP, *SrcPtrQ;
/*********************************************************************************************************/
// NOTE: In principle, the alpha and beta tables are calculated with the formulas below
// Alpha( qp ) = 0.8 * (2^(qp/6) - 1)
// Beta ( qp ) = 0.5 * qp - 7
// The tables actually used have been "hand optimized" though (by Anthony Joch). So, the
// table values might be a little different to formula-generated values. Also, the first
// few values of both tables is set to zero to force the filter off at low qp抯
static const 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} ;
static const 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} ;
static const 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}
} ;
static const char chroma_edge[2][4][4] = //[dir][edge][yuv_format]
{ { {-4, 0, 0, 0},
{-4,-4,-4, 4},
{-4, 4, 4, 8},
{-4,-4,-4, 12}},
{ {-4, 0, 0, 0},
{-4,-4, 4, 4},
{-4, 4, 8, 8},
{-4,-4, 12, 12}}};
static const int pelnum_cr[2][4] = {{0,8,16,16}, {0,8, 8,16}}; //[dir:0=vert, 1=hor.][yuv_format]
void (*GetStrength) (byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir,int edge, int mvlimit,StorablePicture *p);
void GetStrengthNormal (byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir,int edge, int mvlimit,StorablePicture *p);
void GetStrengthMBAff (byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir,int edge, int mvlimit,StorablePicture *p);
void (*EdgeLoopLuma) (ColorPlane pl, imgpel** Img, byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir, int edge, StorablePicture *p);
void EdgeLoopLumaNormal(ColorPlane pl, imgpel** Img, byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir, int edge, StorablePicture *p);
void EdgeLoopLumaMBAff (ColorPlane pl, imgpel** Img, byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir, int edge, StorablePicture *p);
void (*EdgeLoopChroma)(imgpel** Img, byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir, int edge, int uv, StorablePicture *p);
void EdgeLoopChromaNormal(imgpel** Img, byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir, int edge, int uv, StorablePicture *p);
void EdgeLoopChromaMBAff(imgpel** Img, byte Strength[16],ImageParameters *img, Macroblock *MbQ, int dir, int edge, int uv, StorablePicture *p);
void DeblockMb(ImageParameters *img, StorablePicture *p, int MbQAddr);
int compute_deblock_strength(char **list0_refIdxArr, char **list1_refIdxArr, int64 **list0_refPicIdArr, int64 **list1_refPicIdArr,
short ***list0_mv, short ***list1_mv, int blk_y, int blk_x, int blk_y2, int blk_x2, int mvlimit);
/*!
*****************************************************************************************
* \brief
* Filter all macroblocks in order of increasing macroblock address.
*****************************************************************************************
*/
void DeblockPicture(ImageParameters *img, StorablePicture *p)
{
unsigned i;
if (p->MbaffFrameFlag == 1)
{
GetStrength = GetStrengthMBAff;
EdgeLoopLuma = EdgeLoopLumaMBAff;
EdgeLoopChroma = EdgeLoopChromaMBAff;
}
else
{
GetStrength = GetStrengthNormal;
EdgeLoopLuma = EdgeLoopLumaNormal;
EdgeLoopChroma = EdgeLoopChromaNormal;
}
for (i = 0; i < p->PicSizeInMbs; i++)
{
DeblockMb( img, p, i ) ;
}
}
/*!
*****************************************************************************************
* \brief
* Deblocking filter for one macroblock.
*****************************************************************************************
*/
void DeblockMb(ImageParameters *img, StorablePicture *p, int MbQAddr)
{
int EdgeCondition;
int dir, edge;
byte Strength[16];
int mb_x, mb_y;
int filterNon8x8LumaEdgesFlag[4] = {1,1,1,1};
int filterLeftMbEdgeFlag;
int filterTopMbEdgeFlag;
int fieldModeMbFlag;
int mvlimit = 4;
int i, StrengthSum;
Macroblock *MbQ = &(img->mb_data[MbQAddr]) ; // current Mb
imgpel **imgY = p->imgY;
imgpel ***imgUV = p->imgUV;
int edge_cr;
// return, if filter is disabled
if (MbQ->DFDisableIdc==1)
{
img->DeblockCall = 0;
return;
}
img->DeblockCall = 1;
get_mb_pos (MbQAddr, img->mb_size[IS_LUMA], &mb_x, &mb_y);
filterLeftMbEdgeFlag = (mb_x != 0);
filterTopMbEdgeFlag = (mb_y != 0);
if (MbQ->mb_type == I8MB)
assert(MbQ->luma_transform_size_8x8_flag);
filterNon8x8LumaEdgesFlag[1] =
filterNon8x8LumaEdgesFlag[3] = !(MbQ->luma_transform_size_8x8_flag);
if (p->MbaffFrameFlag && mb_y == MB_BLOCK_SIZE && MbQ->mb_field)
filterTopMbEdgeFlag = 0;
fieldModeMbFlag = (p->structure!=FRAME) || (p->MbaffFrameFlag && MbQ->mb_field);
if (fieldModeMbFlag)
mvlimit = 2;
if (MbQ->DFDisableIdc==2)
{
// don't filter at slice boundaries
filterLeftMbEdgeFlag = MbQ->mbAvailA;
// if this the bottom of a frame macroblock pair then always filter the top edge
filterTopMbEdgeFlag = (p->MbaffFrameFlag && !MbQ->mb_field && (MbQAddr & 0x01)) ? 1 : MbQ->mbAvailB;
}
img->current_mb_nr = MbQAddr;
CheckAvailabilityOfNeighbors(MbQ);
for( dir = 0 ; dir < 2 ; dir++ ) // filter first vertical edges, followed by horizontal
{
EdgeCondition = (dir && filterTopMbEdgeFlag) || (!dir && filterLeftMbEdgeFlag); // can not filter beyond picture boundaries
for( edge=0; edge<4 ; edge++ ) // first 4 vertical strips of 16 pel
{ // then 4 horizontal
if( edge || EdgeCondition )
{
edge_cr = chroma_edge[dir][edge][p->chroma_format_idc];
GetStrength(Strength, img, MbQ, dir, edge << 2, mvlimit, p); // Strength for 4 blks in 1 stripe
StrengthSum = Strength[0];
for (i = 1; i < MB_BLOCK_SIZE && StrengthSum == 0 ; i++)
{
StrengthSum += (int) Strength[i];
}
if( StrengthSum ) // only if one of the 16 Strength bytes is != 0
{
if (filterNon8x8LumaEdgesFlag[edge])
{
EdgeLoopLuma( PLANE_Y, imgY, Strength, img, MbQ, dir, edge << 2, p) ;
if( active_sps->chroma_format_idc==YUV444 && !IS_INDEPENDENT(img) )
{
EdgeLoopLuma(PLANE_U, imgUV[0], Strength, img, MbQ, dir, edge << 2, p);
EdgeLoopLuma(PLANE_V, imgUV[1], Strength, img, MbQ, dir, edge << 2, p);
}
}
if (active_sps->chroma_format_idc==YUV420 || active_sps->chroma_format_idc==YUV422)
{
if( (imgUV != NULL) && (edge_cr >= 0))
{
EdgeLoopChroma( imgUV[0], Strength, img, MbQ, dir, edge_cr, 0, p);
EdgeLoopChroma( imgUV[1], Strength, img, MbQ, dir, edge_cr, 1, p);
}
}
}
if (dir && !edge && !MbQ->mb_field && mixedModeEdgeFlag)
{
// this is the extra horizontal edge between a frame macroblock pair and a field above it
img->DeblockCall = 2;
GetStrength(Strength, img, MbQ, dir, MB_BLOCK_SIZE, mvlimit, p); // Strength for 4 blks in 1 stripe
//if( *((int*)Strength) ) // only if one of the 4 Strength bytes is != 0
{
if (filterNon8x8LumaEdgesFlag[edge])
{
EdgeLoopLuma(PLANE_Y, imgY, Strength, img, MbQ, dir, MB_BLOCK_SIZE, p) ;
if( active_sps->chroma_format_idc==YUV444 && !IS_INDEPENDENT(img) )
{
EdgeLoopLuma(PLANE_U, imgUV[0], Strength, img, MbQ, dir, MB_BLOCK_SIZE, p) ;
EdgeLoopLuma(PLANE_V, imgUV[1], Strength, img, MbQ, dir, MB_BLOCK_SIZE, p) ;
}
}
if (active_sps->chroma_format_idc==YUV420 || active_sps->chroma_format_idc==YUV422)
{
if( (imgUV != NULL) && (edge_cr >= 0))
{
EdgeLoopChroma( imgUV[0], Strength, img, MbQ, dir, MB_BLOCK_SIZE, 0, p) ;
EdgeLoopChroma( imgUV[1], Strength, img, MbQ, dir, MB_BLOCK_SIZE, 1, p) ;
}
}
}
img->DeblockCall = 1;
}
}
}//end edge
}//end loop dir
img->DeblockCall = 0;
}
/*!
*********************************************************************************************
* \brief
* returns a buffer of 16 Strength values for one stripe in a mb (for different Frame or Field types)
*********************************************************************************************
*/
#define ANY_INTRA (MbP->mb_type==I4MB||MbP->mb_type==I8MB||MbP->mb_type==I16MB||MbP->mb_type==IPCM||MbQ->mb_type==I4MB||MbQ->mb_type==I8MB||MbQ->mb_type==I16MB||MbQ->mb_type==IPCM)
void GetStrengthNormal(byte Strength[MB_BLOCK_SIZE], ImageParameters *img, Macroblock *MbQ, int dir, int edge, int mvlimit, StorablePicture *p)
{
static int64 ref_p0,ref_p1,ref_q0,ref_q1;
static int blkP, blkQ, idx;
static int blk_x, blk_x2, blk_y, blk_y2 ;
static int xQ, yQ;
static int mb_x, mb_y;
static PixelPos pixP, pixMB;
static byte StrValue;
if ((p->slice_type==SP_SLICE)||(p->slice_type==SI_SLICE) )
{
// Set strength to either 3 or 4 regardless of pixel position
StrValue = (edge == 0 && (((p->structure==FRAME)) || ((p->structure != FRAME) && !dir))) ? 4 : 3;
memset(&Strength[0], (byte) StrValue, MB_BLOCK_SIZE * sizeof(byte));
}
else
{
xQ = dir ? 0 : edge - 1;
yQ = dir ? (edge < 16 ? edge - 1: 0) : 0;
getNeighbour(MbQ, xQ, yQ, img->mb_size[IS_LUMA], &pixMB);
pixP = pixMB;
MbP = &(img->mb_data[pixP.mb_addr]);
if (!ANY_INTRA)
{
PicMotionParams *motion = &p->motion;
list0_refPicIdArr = motion->ref_pic_id[LIST_0];
list1_refPicIdArr = motion->ref_pic_id[LIST_1];
list0_mv = motion->mv[LIST_0];
list1_mv = motion->mv[LIST_1];
list0_refIdxArr = motion->ref_idx[LIST_0];
list1_refIdxArr = motion->ref_idx[LIST_1];
get_mb_block_pos (MbQ->mbAddrX, &mb_x, &mb_y);
mb_x <<= 2;
mb_y <<= 2;
yQ += dir;
xQ += (1 - dir);
for( idx = 0 ; idx < MB_BLOCK_SIZE ; idx += BLOCK_SIZE )
{
if (dir)
{
xQ = idx;
pixP.x = pixMB.x + idx;
pixP.pos_x = pixMB.pos_x + idx;
}
else
{
yQ = idx;
pixP.y = pixMB.y + idx;
pixP.pos_y = pixMB.pos_y + idx;
}
blkQ = (yQ & 0xFFFC) + (xQ >> 2);
blkP = (pixP.y & 0xFFFC) + (pixP.x >> 2);
if( ((MbQ->cbp_blk[0] & ((int64)1 << blkQ )) != 0) || ((MbP->cbp_blk[0] & ((int64)1 << blkP)) != 0) )
StrValue = 2;
else
{
// if no coefs, but vector difference >= 1 set Strength=1
// if this is a mixed mode edge then one set of reference pictures will be frame and the
// other will be field
blk_y = mb_y + (blkQ >> 2);
blk_x = mb_x + (blkQ & 3);
blk_y2 = pixP.pos_y >> 2;
blk_x2 = pixP.pos_x >> 2;
ref_p0 = list0_refIdxArr[blk_y ][blk_x ] < 0 ? INT64_MIN : list0_refPicIdArr[blk_y ][blk_x ];
ref_q0 = list0_refIdxArr[blk_y2][blk_x2] < 0 ? INT64_MIN : list0_refPicIdArr[blk_y2][blk_x2];
ref_p1 = list1_refIdxArr[blk_y ][blk_x ] < 0 ? INT64_MIN : list1_refPicIdArr[blk_y ][blk_x ];
ref_q1 = list1_refIdxArr[blk_y2][blk_x2] < 0 ? INT64_MIN : list1_refPicIdArr[blk_y2][blk_x2];
if ( ((ref_p0==ref_q0) && (ref_p1==ref_q1)) || ((ref_p0==ref_q1) && (ref_p1==ref_q0)))
{
// 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)
{
if (ref_p0 == INT64_MIN)
{
StrValue = (byte) (
(iabs( list1_mv[blk_y][blk_x][0] - list1_mv[blk_y2][blk_x2][0]) >= 4) |
(iabs( list1_mv[blk_y][blk_x][1] - list1_mv[blk_y2][blk_x2][1]) >= mvlimit));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -