解码端去方块滤波代码详述Word格式.docx
《解码端去方块滤波代码详述Word格式.docx》由会员分享,可在线阅读,更多相关《解码端去方块滤波代码详述Word格式.docx(24页珍藏版)》请在冰豆网上搜索。
(Min):
(((Val)>
(Max))?
(Max):
(Val)))
//NOTE:
tochangethetablesbelowforinstancewhentheQPdoublingischangedfrom6to8values
//sendane-mailtoPeter.List@t-togetalittleprogrammthatcalculatesthemautomatically
///////////////////////////////
//标准204页的表8-16或毕书141页的表6.23
byteALPHA_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};
byteBETA_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};
//这边对应标准206页的表8-17或毕书144页的表6.24
//但是稍微有点不同,二维数组中的52指量化参数,5指Bs强度从0-4
//从表中知道,Bs=3和4时,他们的CLIP_TAB是相同的
byteCLIP_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,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}
};
voidGetStrength(byteStrength[16],structimg_par*img,intMbQAddr,intdir,intedge,intmvlimit,StorablePicture*p);
voidEdgeLoop(byte**Img,byteStrength[16],structimg_par*img,intMbQAddr,intAlphaC0Offset,intBetaOffset,intdir,intedge,intwidth,intyuv);
voidDeblockMb(ImageParameters*img,StorablePicture*p,intMbQAddr,intflag);
voidCheckNeighbors(intmb_nr);
voidsearchErrorMB(int*errorMB,intdownMB,intrightMB);
/*!
*****************************************************************************************
*\brief
*Filterallmacroblocksinorderofincreasingmacroblockaddress.
*/
//deblock会减轻block效应,但同时会导致画面模糊,不过这样看起来会舒服很多,
//在某些方面来说确实是“提高”质量吧。
voidDeblockPicture(ImageParameters*img,StorablePicture*p,intflag,int*errorMB)
unsignedinti;
unsignedintcurrLen=0;
intdownMB,rightMB;
if(flag)
{
for(i=0;
i<
p->
PicSizeInMbs;
i++)//循环遍历图像内的所有宏块
DeblockMb(img,p,i,flag);
}
else
while(errorMB[currLen]!
=errorMBInit)
currLen++;
i=0;
while(errorMB[i]!
=errorMBInit&
&
i<
currLen)
downMB=errorMB[i]+p->
PicWidthInMbs;
rightMB=errorMB[i]+1;
searchErrorMB(errorMB,downMB,rightMB);
i++;
DeblockMb(img,p,errorMB[i],flag);
}
*Deblockingfilterforonemacroblock.
voidDeblockMb(ImageParameters*img,StorablePicture*p,intMbQAddr,intflag)
intEdgeCondition;
intdir,edge;
byteStrength[16];
intmb_x,mb_y;
intfilterLeftMbEdgeFlag;
intfilterTopMbEdgeFlag;
intfieldModeMbFlag;
intmvlimit=4;
inti,StrengthSum;
Macroblock*MbQ;
byte**imgY=p->
imgY;
byte***imgUV=p->
imgUV;
img->
DeblockCall=1;
//滤波的标志位
get_mb_pos(MbQAddr,&
mb_x,&
mb_y);
//MbQAddr是0~nOfMB的序号
//mb_x和mb_y表示当前宏块的左上顶点的整像素的横纵坐标
filterLeftMbEdgeFlag=(mb_x!
=0);
filterTopMbEdgeFlag=(mb_y!
//为什么要判断filterLeftMbEdgeFlag和filterTopMbEdgeFlag
//因为对于一幅图像的第一行和第一列是没有上宏块和左宏块的
MbQ=&
(img->
mb_data[MbQAddr]);
//currentMb
if(p->
MbaffFrameFlag&
mb_y==16&
MbQ->
mb_field)
filterTopMbEdgeFlag=0;
/*
标准中对于变量fieldModeMbFlag的说明
-Ifanyofthefollowingconditionsistrue,fieldModeMbFlagissetequalto1.
-field_pic_flagisequalto1
-MbaffFrameFlagisequalto1andthemacroblockCurrMbAddrisafieldmacroblock
-Otherwise,fieldModeMbFlagissetequalto0.
fieldModeMbFlag=(p->
structure!
=FRAME)||(p->
mb_field);
NOTE-Averticaldifferenceof4inunitsofquarterlumaframesamples
isadifferenceof2inunitsofquarterlumafieldsamples
对于场,标准规定mvlimit=2
if(fieldModeMbFlag)
mvlimit=2;
//else
//mvlimit=4;
//return,iffilterisdisabled
//MbQ->
LFDisableIdc指定了在块的边界是否要用滤波,同时指明哪个块的边界不用块的滤波
if(MbQ->
LFDisableIdc==1){
DeblockCall=0;
return;
当LFDisableIdc没有出现在SliceHeader中,LFDisableIdc的值推断为0
LFDisableIdc的值范围在0-2之间
However,forpurposesofdeterminingwhichedgesaretobefiltered
whendisable_deblocking_filter_idcisequalto2,
macroblocksindifferentslicesareconsiderednotavailable
duringspecifiedstepsoftheoperationofthedeblockingfilterprocess.
LFDisableIdc==2)
//don'
tfilteratsliceboundaries
//标准上说的很明白,当LFDisableIdc等于2时,来自不同Slice的宏块视为不可用
//在程序中判断一个宏块的ABCD是否可用,就是判断是否在同一个Slice中
filterLeftMbEdgeFlag=MbQ->
mbAvailA;
filterTopMbEdgeFlag=MbQ->
mbAvailB;
current_mb_nr=MbQAddr;
CheckAvailabilityOfNeighbors();
//检测周围A,B,C,D四个宏块的可用度
CheckNeighbors(MbQAddr);
for(dir=0;
dir<
2;
dir++)//verticaledges,thanhoricontaledges
EdgeCondition=(dir&
filterTopMbEdgeFlag)||(!
dir&
filterLeftMbEdgeFlag);
//cannotfilterbeyondpictureboundaries
for(edge=0;
edge<
4;
edge++)//first4verticalstripsof16pel
{//then4horicontal
//现在对于这个判断条件应该很清楚了
//对于edge=1,2,3当然不用关心EdgeCondition
//但是当edge=0时,就要考虑左宏块或上宏块是否可用
if(edge||EdgeCondition)
GetStrength(Strength,img,MbQAddr,dir,edge,mvlimit,p);
//Strengthfor4blksin1stripe
StrengthSum=Strength[0];
for(i=1;
16;
i++)StrengthSum+=Strength[i];
if(StrengthSum)//onlyifoneofthe16Strengthbytesis!
=0
EdgeLoop(imgY,Strength,img,MbQAddr,MbQ->
LFAlphaC0Offset,MbQ->
LFBetaOffset,dir,edge,p->
size_x,0);
//!
(edge&
1)表明只有当edge=0,2时成立
//调用EdgeLoop的时候有edge/2操作,转换到0和1
if((imgUV!
=NULL)&
!
1))
EdgeLoop(imgUV[0],Strength,img,MbQAddr,MbQ->
LFBetaOffset,dir,edge/2,p->
size_x_cr,1);
EdgeLoop(imgUV[1],Strength,img,MbQAddr,MbQ->
//thisistheextrahorizontaledgebetweenaframemacroblockpairandafieldaboveit
if(dir&
edge&
MbQ->
mb_field&
mixedModeEdgeFlag)
DeblockCall=2;
GetStrength(Strength,img,MbQAddr,dir,4,mvlimit,p);
if(*((int*)Strength))//onlyifoneofthe4Strengthbytesis!
LFBetaOffset,dir,4,p->
}//if(edge||EdgeCondition)
}//for(edge=0;
edge++)
}//for(dir=0;
dir++)
}
/*!
*********************************************************************************************
*returnsabufferof16Strengthvaluesforonestripeinamb(fordifferentFrametypes)
///////////////////////////////////////////////////////////////////////////////////////
//这一块在程序并没有真正用到
intININT_STRENGTH[4]={0x04040404,0x03030303,0x03030303,0x03030303};
byteBLK_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}}};
byteBLK_4_TO_8[16]={0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3};
#defineANY_INTRA(MbP->
mb_type==I4MB||MbP->
mb_type==I16MB||MbP->
mb_type==IPCM||MbQ->
mb_type==I4MB||MbQ->
mb_type==I16MB||MbQ->
mb_type==IPCM)
//输出Bs,处理以4x4块为基本单位
//GetStrength(Strength,img,MbQAddr,dir,edge,mvlimit,p);
//dir=0表示现在处理的是垂直方向的边界,dir=1表示现在处理的是水平方向的边界
//对照标准8.7.2.1,为什么选用P和Q来命名宏块,查