📄 pred.cpp
字号:
/*************************************************************************
AVS1-P2视频解码器源码
版权所有:联合信源数字音视频技术(北京)有限公司, (c) 2005-2006
AVS1-P2 Video Decoder Source Code
(c) Copyright, NSCC All Rights Reserved, 2005-2006
*************************************************************************
Distributed under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*************************************************************************/
/*************************************************************************
文件名称: pred.cpp
描 述: mv 预测
*************************************************************************/
/*************************************************************************
Revision History
data Modification Author
2005-3-2 Created jthou
*************************************************************************/
#include "pred.h"
#include "define.h"
#include "global.h"
#include "block.h"
AVS_HRESULT IntraPredLuma(MBINFO* pMbInfo, const AVS_BYTE* pbCurrY, AVS_DWORD dwMbIndex, AVS_DWORD dwImgWidth, AVS_DWORD dwImgHeight, AVS_DWORD dwBlockNo, AVS_BYTE* pPred, AVS_DWORD dwImgX, AVS_DWORD dwImgY)
{
AVS_BOOL LeftBlockAvailable = FALSE;
AVS_BOOL UpBlockAvailable = FALSE;
AVS_BOOL LeftDownBlockAvailable = FALSE;
AVS_BOOL UpRightBlockAvailable = FALSE;
AVS_INT intraPredModeA = -1, intraPredModeB = -1;
AVS_INT predIntraPredMode = -1;
AVS_INT IntraLumaPredMode = -1;
AVS_INT mostpredIntraPredMode = -1;
AVS_INT BlockX = dwImgX >> 3;
AVS_INT BlockY = dwImgY >> 3;
AVS_INT dwMb8Width = dwImgWidth>>3;
AVS_INT dwMb8Height = dwImgHeight>>3;
AVS_DWORD dwMbWidth = dwImgWidth >> 4;
dwImgWidth = dwImgWidth;
//判断相邻块是否已“可用”
if(BlockY > 0)
UpBlockAvailable = TRUE;
if(BlockY>0 && BlockX<dwMb8Width-1)
UpRightBlockAvailable = TRUE;
if(BlockX > 0)
LeftBlockAvailable = TRUE;
if(BlockX>0 && BlockY<dwMb8Height-1 )
LeftDownBlockAvailable = TRUE;
if(dwBlockNo == 3)
UpRightBlockAvailable = FALSE;
if(dwBlockNo != 0)
LeftDownBlockAvailable = FALSE;
//求预测模式
if(LeftBlockAvailable)
{
if(dwBlockNo == 0 || dwBlockNo == 2)
{
if(pMbInfo[dwMbIndex-1].dwMbType == I_8x8)
intraPredModeA = pMbInfo[dwMbIndex-1].iIntraLumaPredModeNew[dwBlockNo+1];
else
intraPredModeA = 2;
}
else
intraPredModeA = pMbInfo[dwMbIndex].iIntraLumaPredModeNew[dwBlockNo-1];
}
if(UpBlockAvailable)
{
if(dwBlockNo == 0 || dwBlockNo == 1)
{
if(pMbInfo[dwMbIndex-dwMbWidth].dwMbType == I_8x8)
intraPredModeB = pMbInfo[dwMbIndex-dwMbWidth].iIntraLumaPredModeNew[dwBlockNo+2];
else
intraPredModeB = 2;
}
else
intraPredModeB = pMbInfo[dwMbIndex].iIntraLumaPredModeNew[dwBlockNo-2];
}
if (intraPredModeA == -1 || intraPredModeB == -1)
{
predIntraPredMode = 2;
}
else
{
predIntraPredMode = min(intraPredModeA, intraPredModeB);
}
if(pMbInfo[dwMbIndex].bPredModeFlag[dwBlockNo])
{
IntraLumaPredMode = predIntraPredMode;
}
else
{
if(pMbInfo[dwMbIndex].iIntraLumaPredMode[dwBlockNo] < predIntraPredMode)
IntraLumaPredMode = pMbInfo[dwMbIndex].iIntraLumaPredMode[dwBlockNo];
else
IntraLumaPredMode = pMbInfo[dwMbIndex].iIntraLumaPredMode[dwBlockNo]+1;
}
pMbInfo[dwMbIndex].iIntraLumaPredModeNew[dwBlockNo] = IntraLumaPredMode;
AVS_BYTE c[18], r[18];
AVS_INT i, j;
if(LeftBlockAvailable)
{
for(i=0; i<8; i++)
c[i+1] = *(pbCurrY + (dwImgY+i)*dwImgWidth + dwImgX-1);
c[0] = c[1];
for(i=0; i<9; i++)
{
c[i+9] = c[8];
}
}
if(UpBlockAvailable)
{
for(i=0; i<8; i++)
r[i+1] = *(pbCurrY+(dwImgY-1)*dwImgWidth + dwImgX+i);
r[0] = r[1];
for(i=0; i<9; i++)
{
r[i+9] = r[8];
}
}
if(LeftDownBlockAvailable)
{
for(i=0; i<8; i++)
c[i+9] = *(pbCurrY+(dwImgY+8+i)*dwImgWidth + dwImgX-1);
c[17] = c[16];
}
if(UpRightBlockAvailable)
{
for(i=0; i<8; i++)
r[i+9] = *(pbCurrY+(dwImgY-1)*dwImgWidth + dwImgX+8+i);
r[17] =r[16];
}
if(UpBlockAvailable && LeftBlockAvailable)
{
r[0] = c[0] = *(pbCurrY+(dwImgY-1)*dwImgWidth + dwImgX-1);
}
switch(IntraLumaPredMode)
{
case Intra_8x8_Vertical:
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[i*8+j]=r[j+1];
break;
case Intra_8x8_Horizontal:
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[i*8+j]=c[i+1];
break;
case Intra_8x8_DC:
if(!UpBlockAvailable && !LeftBlockAvailable)
{
for(i=0;i<8;i++)
for(j=0;j<8;j++)
pPred[i*8+j] = 128;
}
else if(UpBlockAvailable && !LeftBlockAvailable)
{
for(i=0;i<8;i++)
for(j=0;j<8;j++)
//pPred[j*8+i] = (r[i]+2*r[i+1]+r[i+2]+2)>>2;
pPred[i*8+j] = (r[j]+2*r[j+1]+r[j+2]+2)>>2;
}
else if(!UpBlockAvailable && LeftBlockAvailable)
{
for(i=0; i<8; i++)
for(j=0; j<8; j++)
//pPred[j*8+i] = (c[j]+2*c[j+1]+c[j+2]+2)>>2;
pPred[i*8+j] = (c[i]+2*c[i+1]+c[i+2]+2)>>2;
}
else if(UpBlockAvailable && LeftBlockAvailable)
{
for(i=0; i<8; i++)
for(j=0; j<8; j++)
//pPred[j*8+i] = (((r[i]+2*r[i+1]+r[i+2]+2)>>2)+((c[j]+2*c[j+1]+c[j+2]+2)>>2))>>1;
pPred[i*8+j] = (((r[j]+2*r[j+1]+r[j+2]+2)>>2)+((c[i]+2*c[i+1]+c[i+2]+2)>>2))>>1;
}
break;
case Intra_8x8_Down_Left:
for(i=0; i<8; i++)
{
for(j=0; j<8; j++)
//pPred[j*8+i] = (((r[i+j+1]+2*r[i+j+2]+r[i+j+3]+2)>>2)+((c[i+j+1]+2*c[i+j+2]+c[i+j+3]+2)>>2))>>1;
pPred[i*8+j] = (((r[i+j+1]+2*r[i+j+2]+r[i+j+3]+2)>>2)+((c[i+j+1]+2*c[i+j+2]+c[i+j+3]+2)>>2))>>1;
}
break;
case Intra_8x8_Down_Right:
for(i=0; i<8; i++)
{
for(j=0; j<8; j++)
{
if(i==j)
pPred[i*8+j] = (c[1]+2*r[0]+r[1]+2)>>2;
if(j>i)
pPred[i*8+j] = (r[j-i+1]+2*r[j-i]+r[j-i-1]+2)>>2;
if(j<i)
pPred[i*8+j] = (c[i-j+1]+2*c[i-j]+c[i-j-1]+2)>>2;
}
}
break;
default:
break;
//erro!
}
return AVS_NOERROR;
}
AVS_HRESULT IntraPredChroma(MBINFO* pMbInfo, const AVS_BYTE* pbCurrUV, AVS_DWORD dwMbIndex, AVS_DWORD dwMbWidth, AVS_DWORD dwMbHeight, AVS_BYTE* pPred, AVS_DWORD dwUVX, AVS_DWORD dwUVY)
{
AVS_INT i, j;
AVS_BOOL UpBlockAvailable = FALSE;
AVS_BOOL LeftBlockAvailable = FALSE;
AVS_INT BlockX = dwMbIndex%dwMbWidth;
AVS_INT BlockY = dwMbIndex/dwMbWidth;
AVS_INT dwUVWidth = dwMbWidth*8;
if(BlockX > 0)
LeftBlockAvailable = TRUE;
if(BlockY > 0)
UpBlockAvailable = TRUE;
AVS_INT r[10], c[10];
if(LeftBlockAvailable)
{
for(i=0; i<8; i++)
c[i+1] = *(pbCurrUV+(dwUVY+i)*dwUVWidth+dwUVX-1);
c[0] = c[1];
c[9] = c[8];
}
if(UpBlockAvailable)
{
for(i=0; i<8; i++)
r[i+1] = *(pbCurrUV+(dwUVY-1)*dwUVWidth+dwUVX+i);
r[0] = r[1];
r[9] = r[8];
}
if(LeftBlockAvailable && UpBlockAvailable)
{
c[0] = r[0] = *(pbCurrUV+(dwUVY-1)*dwUVWidth+dwUVX-1);
}
AVS_INT intraChromaPreMode = pMbInfo[dwMbIndex].dwintraChromaPredMode;
AVS_INT ih=0, iv=0, ia=0, ib=0, ic=0;
switch(intraChromaPreMode)
{
case Intra_Chroma_DC:
if(LeftBlockAvailable && UpBlockAvailable)
{
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[j*8+i] = (((r[i]+2*r[i+1]+r[i+2]+2)>>2)+((c[j]+2*c[j+1]+c[j+2]+2)>>2))>>1;
}
if(!LeftBlockAvailable && UpBlockAvailable)
{
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[j*8+i] = (r[i]+2*r[i+1]+r[i+2]+2)>>2;
}
if(LeftBlockAvailable && !UpBlockAvailable)
{
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[j*8+i] = (c[j]+2*c[j+1]+c[j+2]+2)>>2;
}
if(!LeftBlockAvailable && !UpBlockAvailable)
{
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[j*8+i] = 128;
}
break;
case Intra_Chroma_Horizontal:
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[j*8+i] = c[j+1];
break;
case Intra_Chroma_Vertical:
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[j*8+i] = r[i+1];
break;
case Intra_Chroma_Plane:
for(i=0; i<=3; i++)
{
ih += (i+1)*(r[5+i]-r[3-i]);
iv += (i+1)*(c[5+i]-c[3-i]);
}
ia = (r[8]+c[8])<<4;
ib = (17*ih+16)>>5;
ic = (17*iv+16)>>5;
for(i=0; i<8; i++)
for(j=0; j<8; j++)
pPred[i*8+j] = Clip((ia+(j-3)*ib+(i-3)*ic+16)>>5);
break;
default:
// error!
break;
}
return AVS_NOERROR;
}
MOTIONVECTOR ScaleMv(MOTIONVECTOR* pMv, AVS_INT iDistance1, AVS_INT iDistance2)
{
MOTIONVECTOR mv={0,0};
if(pMv->x != 0)
mv.x = sign1(pMv->x)*((abs(pMv->x)*iDistance1*(512/iDistance2)+256) >>9);
if(pMv->y != 0)
mv.y = sign1(pMv->y)*((abs(pMv->y)*iDistance1*(512/iDistance2)+256) >>9);
return mv;
}
MOTIONVECTOR ScalePredMv(MOTIONVECTOR* pMvA, MOTIONVECTOR* pMvB, MOTIONVECTOR* pMvC, AVS_INT iDistance1, AVS_INT iDistanceA, AVS_INT iDistanceB, AVS_INT iDistanceC)
{
MOTIONVECTOR MVA, MVB, MVC;
MVA = ScaleMv(pMvA, iDistance1, iDistanceA);
MVB = ScaleMv(pMvB, iDistance1, iDistanceB);
MVC = ScaleMv(pMvC, iDistance1, iDistanceC);
AVS_INT VAB = abs(MVA.x - MVB.x) + abs(MVA.y - MVB.y);
AVS_INT VBC = abs(MVB.x - MVC.x) + abs(MVB.y - MVC.y);
AVS_INT VCA = abs(MVC.x - MVA.x) + abs(MVC.y - MVA.y);
AVS_INT FMV = Median(VAB, VBC, VCA);
if(FMV == VAB)
return MVC;
else if(FMV == VBC)
return MVA;
else
return MVB;
}
AVS_HRESULT InterPredLuma16x16(MBINFO* pMbInfo, AVS_INT dwMbIndex, const AVS_BYTE* pbRefY, AVS_INT dwMbWidth, AVS_INT dwMbHeight, AVS_INT iBlockDistance, AVS_INT dirBw, AVS_BYTE* pPred)
{
AVS_BOOL A_BlockAvailable = FALSE;
AVS_BOOL B_BlockAvailable = FALSE;
AVS_BOOL C_BlockAvailable = FALSE;
AVS_BOOL D_BlockAvailable = FALSE;
AVS_INT BlockDistanceA=1;
AVS_INT BlockDistanceB=1;
AVS_INT BlockDistanceC=1;
AVS_INT BlockDistanceD=1;
AVS_INT RefIdxA = -1;
AVS_INT RefIdxB = -1;
AVS_INT RefIdxC = -1;
AVS_INT RefIdxD = -1;
MOTIONVECTOR mvA={0,0}, mvB={0,0}, mvC={0,0}, mvD={0,0}, mvE={0,0};
MOTIONVECTOR MVEPred={0,0};
AVS_INT MbX = dwMbIndex%dwMbWidth;
AVS_INT MbY = dwMbIndex/dwMbWidth;
if(MbX>0)
A_BlockAvailable = TRUE;
if(MbY>0)
B_BlockAvailable = TRUE;
if(MbX>0 && MbY>0)
D_BlockAvailable = TRUE;
if(MbY>0 && MbX<dwMbWidth-1)
C_BlockAvailable = TRUE;
if(!A_BlockAvailable || pMbInfo[dwMbIndex-1].dwMbType == I_8x8 ||
(pMbInfo[dwMbIndex-1].predDir[1] != pMbInfo[dwMbIndex].predDir[0] &&
pMbInfo[dwMbIndex-1].predDir[1] != PREDDIRSYM))
{
mvA.x = mvA.y = 0;
BlockDistanceA = 1;
RefIdxA = -1;
}
else
{
if(!dirBw)
{
mvA = pMbInfo[dwMbIndex-1].mv[1];
BlockDistanceA = pMbInfo[dwMbIndex-1].iBlockDistance[1];
RefIdxA = pMbInfo[dwMbIndex-1].dwMbReferenceIndex[1];
}
else
{
mvA = pMbInfo[dwMbIndex-1].mvBw[1];
BlockDistanceA = pMbInfo[dwMbIndex-1].iBlockDistanceBw[1];
RefIdxA = pMbInfo[dwMbIndex-1].dwMbReferenceIndexBw[1];
}
}
if(!B_BlockAvailable || pMbInfo[dwMbIndex-dwMbWidth].dwMbType == I_8x8 ||
(pMbInfo[dwMbIndex-dwMbWidth].predDir[2] != pMbInfo[dwMbIndex].predDir[0] &&
pMbInfo[dwMbIndex-dwMbWidth].predDir[2] != PREDDIRSYM))
{
mvB.x = mvB.y = 0;
BlockDistanceB = 1;
RefIdxB = -1;
}
else
{
if(!dirBw)
{
mvB = pMbInfo[dwMbIndex-dwMbWidth].mv[2];
BlockDistanceB = pMbInfo[dwMbIndex-dwMbWidth].iBlockDistance[2];
RefIdxB = pMbInfo[dwMbIndex-dwMbWidth].dwMbReferenceIndex[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -