📄 mc.cpp
字号:
ppxlcRefBot = ppxlcRef + m_iFrameWidthY; //UPln -> pixels (xInt,yInt+1);
for (ix = 0; ix < iSize; ix++)
ppxlcPred [ix] = (ppxlcRef [ix] + ppxlcRefBot [ix] + 1 - iRoundingControl) >> 1;
ppxlcRef = ppxlcRefBot;
ppxlcPred += MB_SIZE;
}
}
else { // bXSubPxl && bYSubPxl
for (iy = 0; iy < iSize; iy++) {
ppxlcRefBot = ppxlcRef + m_iFrameWidthY; //UPln -> pixels (xInt,yInt+1);
for (ix = 0; ix < iSize; ix++){
ppxlcPred [ix] = (
ppxlcRef [ix + 1] + ppxlcRef [ix] +
ppxlcRefBot [ix + 1] + ppxlcRefBot [ix] + 2 - iRoundingControl
) >> 2;
}
ppxlcRef = ppxlcRefBot;
ppxlcPred += MB_SIZE;
}
}
}
}
}
Void CVideoObject::motionCompDirectMode( // Interlaced direct mode
CoordI x, CoordI y,
CMBMode *pmbmd,
const CMotionVector *pmvRef,
CRct *prctMVLimitFwd, CRct *prctMVLimitBak,
Int plane // plane=1 for grey scale, plane=0 for texture, 02-17-99
)
{
Int* rgiMvRound = NULL;
UInt uiDivisor = 0;
Int xRefUVF,yRefUVF,xRefUVB,yRefUVB;
// begin of new changes 10/21/98
Int iMBX,iMBY;
const CMBMode *pmbmdRef;
if(m_volmd.fAUsage != RECTANGLE)
{
iMBX=(x-m_rctCurrVOPY.left)/MB_SIZE;
iMBY=(y-m_rctCurrVOPY.top)/MB_SIZE;
pmbmdRef= m_rgmbmdRef +
(iMBX+iMBY*m_iNumMBXRef);
}
else
{
iMBX=x/MB_SIZE;
iMBY=y/MB_SIZE;
pmbmdRef= m_rgmbmdRef +
iMBX+iMBY*m_iNumMBXRef;
}
// end of new changes 10/21/98
if (pmbmdRef->m_rgTranspStatus[0]==ALL) {
static CMotionVector mvZero[5];
pmvRef = mvZero;
}
if ((iMBX<m_iNumMBXRef && iMBX>=0 && iMBY<m_iNumMBYRef && iMBY>=0)&& // new change 10/21/98
(pmbmdRef->m_bFieldMV&&pmbmdRef->m_rgTranspStatus[0]!=ALL)) {
static I8 iTROffsetTop[] = { 0, 0, 1, 1, 0, 0, -1, -1 };
static I8 iTROffsetBot[] = { -1, 0, -1, 0, 1, 0, 1, 0 };
CoordI iXFwdTop, iXFwdBot, iXBakTop, iXBakBot;
CoordI iYFwdTop, iYFwdBot, iYBakTop, iYBakBot;
const CMotionVector *pmvRefTop, *pmvRefBot;
Int iTopRefFldOffset = 0, iBotRefFldOffset = 0;
Int iCode = (Int)(vopmd().bTopFieldFirst) << 2;
pmbmd->m_bFieldMV = 1; // set field direct mode for grey scale // new change 02-19-99
assert((pmbmdRef->m_dctMd != INTRA) && (pmbmdRef->m_dctMd != INTRAQ));
if (pmbmdRef->m_bForwardTop) {
iCode |= 2;
iTopRefFldOffset = 1;
pmvRefTop = pmvRef + 6;
} else
pmvRefTop = pmvRef + 5;
if (pmbmdRef->m_bForwardBottom) {
iCode |= 1;
iBotRefFldOffset = 1;
pmvRefBot = pmvRef + 8;
} else
pmvRefBot = pmvRef + 7;
Int iTempRefDTop = 2*(m_tFutureRef - m_tPastRef) + iTROffsetTop[iCode];
Int iTempRefDBot = 2*(m_tFutureRef - m_tPastRef) + iTROffsetBot[iCode];
Int iTempRefBTop = 2*(m_t - m_tPastRef) + iTROffsetTop[iCode];
Int iTempRefBBot = 2*(m_t - m_tPastRef) + iTROffsetBot[iCode];
assert(iTempRefDTop > 0); assert(iTempRefDBot > 0); assert(iTempRefBTop > 0); assert(iTempRefBBot > 0);
// Find MVs for the top field
iXFwdTop = (pmvRefTop->m_vctTrueHalfPel.x * iTempRefBTop) / iTempRefDTop + pmbmd->m_vctDirectDeltaMV.x;
iYFwdTop = (pmvRefTop->m_vctTrueHalfPel.y * iTempRefBTop) / iTempRefDTop + pmbmd->m_vctDirectDeltaMV.y;
iXBakTop = pmbmd->m_vctDirectDeltaMV.x ? (iXFwdTop - pmvRefTop->m_vctTrueHalfPel.x) :
((pmvRefTop->m_vctTrueHalfPel.x * (iTempRefBTop - iTempRefDTop)) / iTempRefDTop);
iYBakTop = pmbmd->m_vctDirectDeltaMV.y ? (iYFwdTop - pmvRefTop->m_vctTrueHalfPel.y) :
((pmvRefTop->m_vctTrueHalfPel.y * (iTempRefBTop - iTempRefDTop)) / iTempRefDTop);
// Find MVs for the bottom field
iXFwdBot = (pmvRefBot->m_vctTrueHalfPel.x * iTempRefBBot) / iTempRefDBot + pmbmd->m_vctDirectDeltaMV.x;
iYFwdBot = (pmvRefBot->m_vctTrueHalfPel.y * iTempRefBBot) / iTempRefDBot + pmbmd->m_vctDirectDeltaMV.y;
iXBakBot = pmbmd->m_vctDirectDeltaMV.x ? (iXFwdBot - pmvRefBot->m_vctTrueHalfPel.x) :
((pmvRefBot->m_vctTrueHalfPel.x * (iTempRefBBot - iTempRefDBot)) / iTempRefDBot);
iYBakBot = pmbmd->m_vctDirectDeltaMV.y ? (iYFwdBot - pmvRefBot->m_vctTrueHalfPel.y) :
((pmvRefBot->m_vctTrueHalfPel.y * (iTempRefBBot - iTempRefDBot)) / iTempRefDBot);
// Motion compensate the top field forward
iXFwdTop += 2*x; iYFwdTop += 2*y;
limitMVRangeToExtendedBBHalfPel(iXFwdTop, iYFwdTop, prctMVLimitFwd, MB_SIZE);
if (plane==0) { // texture MC // new change 02-19-99
motionCompYField(m_ppxlcPredMBY,
m_pvopcRefQ0->pixelsY() + iTopRefFldOffset * m_iFrameWidthY, iXFwdTop, iYFwdTop);
iXFwdTop -= 2*x; iYFwdTop -= 2*y;
motionCompFieldUV(m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y,
(iXFwdTop & 3) ? ((iXFwdTop >> 1) | 1) : (iXFwdTop >> 1),
(iYFwdTop & 6) ? ((iYFwdTop >> 1) | 2) : (iYFwdTop >> 1), iTopRefFldOffset);
}
else { // plane=1, grey scale MC // begin of new change 02-19-99
motionCompYField(m_ppxlcPredMBA,
m_pvopcRefQ0->pixelsA() + iTopRefFldOffset * m_iFrameWidthY, iXFwdTop, iYFwdTop);
iXFwdTop -= 2*x; iYFwdTop -= 2*y;
} // end of new change 02-19-99
// Motion compensate the top field backward
iXBakTop += 2*x; iYBakTop += 2*y;
limitMVRangeToExtendedBBHalfPel(iXBakTop, iYBakTop, prctMVLimitBak, MB_SIZE);
if (plane==0) { // texture MC // new change 02-19-99
motionCompYField(m_ppxlcPredMBBackY, m_pvopcRefQ1->pixelsY(), iXBakTop, iYBakTop);
iXBakTop -= 2*x; iYBakTop -= 2*y;
motionCompFieldUV(m_ppxlcPredMBBackU, m_ppxlcPredMBBackV, m_pvopcRefQ1, x, y,
(iXBakTop & 3) ? ((iXBakTop >> 1) | 1) : (iXBakTop >> 1),
(iYBakTop & 6) ? ((iYBakTop >> 1) | 2) : (iYBakTop >> 1), 0);
}
else { // plane=1, grey scale MC // begin of new change 02-19-99
motionCompYField(m_ppxlcPredMBBackA, m_pvopcRefQ1->pixelsA(), iXBakTop, iYBakTop);
iXBakTop -= 2*x; iYBakTop -= 2*y;
} // end of new change 02-19-99
// Motion compensate the bottom field forward
iXFwdBot += 2*x; iYFwdBot += 2*y;
limitMVRangeToExtendedBBHalfPel(iXFwdBot, iYFwdBot, prctMVLimitFwd, MB_SIZE);
if (plane==0) { // texture MC // new change 02-19-99
motionCompYField(m_ppxlcPredMBY + MB_SIZE,
m_pvopcRefQ0->pixelsY() + iBotRefFldOffset * m_iFrameWidthY, iXFwdBot, iYFwdBot);
iXFwdBot -= 2*x; iYFwdBot -= 2*y;
motionCompFieldUV(m_ppxlcPredMBU + BLOCK_SIZE, m_ppxlcPredMBV + BLOCK_SIZE, m_pvopcRefQ0, x, y,
(iXFwdBot & 3) ? ((iXFwdBot >> 1) | 1) : (iXFwdBot >> 1),
(iYFwdBot & 6) ? ((iYFwdBot >> 1) | 2) : (iYFwdBot >> 1), iBotRefFldOffset);
}
else { // plane=1, grey scale MC // begin of new change 02-19-99
motionCompYField(m_ppxlcPredMBA + MB_SIZE,
m_pvopcRefQ0->pixelsA() + iBotRefFldOffset * m_iFrameWidthY, iXFwdBot, iYFwdBot);
iXFwdBot -= 2*x; iYFwdBot -= 2*y;
} // end of new change 02-19-99
// Motion compensate the bottom field backward
iXBakBot += 2*x; iYBakBot += 2*y;
limitMVRangeToExtendedBBHalfPel(iXBakBot, iYBakBot, prctMVLimitBak, MB_SIZE);
if (plane==0) { // texture MC // new change 02-19-99
motionCompYField(m_ppxlcPredMBBackY + MB_SIZE, m_pvopcRefQ1->pixelsY() + m_iFrameWidthY,
iXBakBot, iYBakBot);
iXBakBot -= 2*x; iYBakBot -= 2*y;
motionCompFieldUV(m_ppxlcPredMBBackU + BLOCK_SIZE, m_ppxlcPredMBBackV + BLOCK_SIZE, m_pvopcRefQ1, x, y,
(iXBakBot & 3) ? ((iXBakBot >> 1) | 1) : (iXBakBot >> 1),
(iYBakBot & 6) ? ((iYBakBot >> 1) | 2) : (iYBakBot >> 1), 1);
}
else { // plane=1, grey scale MC // begin of new change 02-19-99
motionCompYField(m_ppxlcPredMBBackA + MB_SIZE, m_pvopcRefQ1->pixelsA() + m_iFrameWidthY,
iXBakBot, iYBakBot);
iXBakBot -= 2*x; iYBakBot -= 2*y;
} // end of new change 02-19-99
} else {
Int iTempRefD = m_tFutureRef - m_tPastRef;
Int iTempRefB = m_t - m_tPastRef;
assert(iTempRefD > 0); assert(iTempRefB > 0);
Int iChromaFwdX = 0, iChromaFwdY = 0, iChromaBakX = 0, iChromaBakY = 0;
CVector vctFwd, vctBak;
static I8 iBlkXOffset[] = { 0, 2*BLOCK_SIZE, 0, 2*BLOCK_SIZE };
static I8 iBlkYOffset[] = { 0, 0, 2*BLOCK_SIZE, 2*BLOCK_SIZE };
static Int iMBOffset[] = { 0, BLOCK_SIZE, MB_SIZE*BLOCK_SIZE, MB_SIZE*BLOCK_SIZE + BLOCK_SIZE };
if ((pmbmdRef->m_dctMd == INTRA) || (pmbmdRef->m_dctMd == INTRAQ)) {
static CMotionVector mvZero[5];
pmvRef = mvZero;
}
if(iMBX<m_iNumMBXRef && iMBX>=0 && iMBY<m_iNumMBYRef && iMBY>=0) // new changes 10/21/98
{
if (pmbmdRef -> m_bhas4MVForward) {
for (Int iBlk = 0; iBlk < 4; iBlk++) {
if(pmbmd->m_rgTranspStatus[iBlk+1]!=ALL) {
vctFwd = (pmvRef[iBlk + 1].m_vctTrueHalfPel * iTempRefB) / iTempRefD + pmbmd->m_vctDirectDeltaMV;
vctBak.x = pmbmd->m_vctDirectDeltaMV.x ? (vctFwd.x - pmvRef[iBlk + 1].m_vctTrueHalfPel.x) :
((pmvRef[iBlk + 1].m_vctTrueHalfPel.x * (iTempRefB - iTempRefD)) / iTempRefD);
vctBak.y = pmbmd->m_vctDirectDeltaMV.y ? (vctFwd.y - pmvRef[iBlk + 1].m_vctTrueHalfPel.y) :
((pmvRef[iBlk + 1].m_vctTrueHalfPel.y * (iTempRefB - iTempRefD)) / iTempRefD);
// rounding control is messed up here
motionComp(m_ppxlcPredMBY + iMBOffset[iBlk], m_pvopcRefQ0->pixelsY(), BLOCK_SIZE,
x * 2 + iBlkXOffset[iBlk] + vctFwd.x, y * 2 + iBlkYOffset[iBlk] + vctFwd.y, 0, prctMVLimitFwd);
motionComp(m_ppxlcPredMBBackY + iMBOffset[iBlk], m_pvopcRefQ1->pixelsY(), BLOCK_SIZE,
x * 2 + iBlkXOffset[iBlk] + vctBak.x, y * 2 + iBlkYOffset[iBlk] + vctBak.y, 0, prctMVLimitBak);
iChromaFwdX += vctFwd.x;
iChromaFwdY += vctFwd.y;
iChromaBakX += vctBak.x;
iChromaBakY += vctBak.y;
uiDivisor += 4;
}
}
switch (uiDivisor) {
case 4:
rgiMvRound = grgiMvRound4;
break;
case 8:
rgiMvRound = grgiMvRound8;
break;
case 12:
rgiMvRound = grgiMvRound12;
break;
case 16:
rgiMvRound = grgiMvRound16;
break;
}
xRefUVF = sign (iChromaFwdX) * (rgiMvRound [abs (iChromaFwdX) % uiDivisor] + (abs (iChromaFwdX) / uiDivisor) * 2);
yRefUVF = sign (iChromaFwdY) * (rgiMvRound [abs (iChromaFwdY) % uiDivisor] + (abs (iChromaFwdY) / uiDivisor) * 2);
xRefUVB = sign (iChromaBakX) * (rgiMvRound [abs (iChromaBakX) % uiDivisor] + (abs (iChromaBakX) / uiDivisor) * 2);
yRefUVB = sign (iChromaBakY) * (rgiMvRound [abs (iChromaBakY) % uiDivisor] + (abs (iChromaBakY) / uiDivisor) * 2);
}
else // 16x16
{
vctFwd = (pmvRef[0].m_vctTrueHalfPel * iTempRefB) / iTempRefD + pmbmd->m_vctDirectDeltaMV;
vctBak.x = pmbmd->m_vctDirectDeltaMV.x ? (vctFwd.x - pmvRef[0].m_vctTrueHalfPel.x) :
((pmvRef[0].m_vctTrueHalfPel.x * (iTempRefB - iTempRefD)) / iTempRefD);
vctBak.y = pmbmd->m_vctDirectDeltaMV.y ? (vctFwd.y - pmvRef[0].m_vctTrueHalfPel.y) :
((pmvRef[0].m_vctTrueHalfPel.y * (iTempRefB - iTempRefD)) / iTempRefD);
// rounding control is messed up here
motionComp(m_ppxlcPredMBY, m_pvopcRefQ0->pixelsY(), MB_SIZE,
x * 2 + vctFwd.x, y * 2 + vctFwd.y, 0, prctMVLimitFwd);
motionComp(m_ppxlcPredMBBackY , m_pvopcRefQ1->pixelsY(), MB_SIZE,
x * 2 + vctBak.x, y * 2 + vctBak.y, 0, prctMVLimitBak);
xRefUVF = sign (vctFwd.x) * (grgiMvRound4 [abs (vctFwd.x) % 4] + (abs (vctFwd.x) / 4) * 2);
yRefUVF = sign (vctFwd.y) * (grgiMvRound4 [abs (vctFwd.y) % 4] + (abs (vctFwd.y) / 4) * 2);
xRefUVB = sign (vctBak.x) * (grgiMvRound4 [abs (vctBak.x) % 4] + (abs (vctBak.x) / 4) * 2);
yRefUVB = sign (vctBak.y) * (grgiMvRound4 [abs (vctBak.y) % 4] + (abs (vctBak.y) / 4) * 2);
}
}
// begin of new changes 10/21/98
else
{
vctFwd = pmbmd->m_vctDirectDeltaMV;
vctBak.x = pmbmd->m_vctDirectDeltaMV.x ? vctFwd.x :0;
vctBak.y = pmbmd->m_vctDirectDeltaMV.y ? vctFwd.y :0;
// rounding control is messed up here
motionComp(m_ppxlcPredMBY, m_pvopcRefQ0->pixelsY(), MB_SIZE,
x * 2 + vctFwd.x, y * 2 + vctFwd.y, 0, prctMVLimitFwd);
motionComp(m_ppxlcPredMBBackY , m_pvopcRefQ1->pixelsY(), MB_SIZE,
x * 2 + vctBak.x, y * 2 + vctBak.y, 0, prctMVLimitBak);
xRefUVF = sign (vctFwd.x) * (grgiMvRound4 [abs (vctFwd.x) % 4] + (abs (vctFwd.x) / 4) * 2);
yRefUVF = sign (vctFwd.y) * (grgiMvRound4 [abs (vctFwd.y) % 4] + (abs (vctFwd.y) / 4) * 2);
xRefUVB = sign (vctBak.x) * (grgiMvRound4 [abs (vctBak.x) % 4] + (abs (vctBak.x) / 4) * 2);
yRefUVB = sign (vctBak.y) * (grgiMvRound4 [abs (vctBak.y) % 4] + (abs (vctBak.y) / 4) * 2);
}
// end of new changes 10/21/98
motionCompUV(m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y,
xRefUVF,
yRefUVF,0, prctMVLimitFwd);
motionCompUV(m_ppxlcPredMBBackU, m_ppxlcPredMBBackV, m_pvopcRefQ1, x, y,
xRefUVB,
yRefUVB,0, prctMVLimitBak);
}
}
Void CVideoObject::motionCompOneBVOPReference(
CVOPU8YUVBA *pvopcPred,
MBType type,
CoordI x, CoordI y,
const CMBMode *pmbmd,
const CMotionVector *pmv,
CRct *prctMVLimit
)
{
CVOPU8YUVBA *pvopcRef;
Int topRef, botRef;
if (type == BACKWARD) {
pvopcRef = m_pvopcRefQ1;
topRef = (Int)pmbmd->m_bBackwardTop;
botRef = (Int)pmbmd->m_bBackwardBottom;
} else {
pvopcRef = m_pvopcRefQ0;
topRef = (Int)pmbmd->m_bForwardTop;
botRef = (Int)pmbmd->m_bForwardBottom;
}
if (pmbmd->m_bFieldMV) {
const CMotionVector *pmvTop = pmv + 1 + topRef;
const CMotionVector *pmvBot = pmv + 3 + botRef;
assert((topRef & ~1) == 0); assert((botRef & ~1) == 0);
CoordI iMVX, iMVY;
iMVX = 2*x + pmvTop->m_vctTrueHalfPel.x;
iMVY = 2*y + pmvTop->m_vctTrueHalfPel.y;
limitMVRangeToExtendedBBHalfPel(iMVX, iMVY, prctMVLimit, MB_SIZE);
motionCompYField((PixelC *)pvopcPred->pixelsY(), // Luma top field
pvopcRef->pixelsY() + topRef * m_iFrameWidthY, iMVX, iMVY);
iMVX -= 2*x; iMVY -= 2*y;
motionCompFieldUV((PixelC *)pvopcPred->pixelsU(), // Chroma top field
(PixelC *)pvopcPred->pixelsV(), pvopcRef, x, y,
(iMVX & 3) ? ((iMVX >> 1) | 1) : (iMVX >> 1),
(iMVY & 6) ? ((iMVY >> 1) | 2) : (iMVY >> 1), topRef);
iMVX = 2*x + pmvBot->m_vctTrueHalfPel.x;
iMVY = 2*y + pmvBot->m_vctTrueHalfPel.y;
limitMVRangeToExtendedBBHalfPel(iMVX, iMVY, prctMVLimit, MB_SIZE);
motionCompYField((PixelC *)(pvopcPred->pixelsY()) + MB_SIZE, // Luma bottom field
pvopcRef->pixelsY() + botRef * m_iFrameWidthY, iMVX, iMVY);
iMVX -= 2*x; iMVY -= 2*y;
motionCompFieldUV((PixelC *)(pvopcPred->pixelsU()) + BLOCK_SIZE, // Chroma bottom field
(PixelC *)(pvopcPred->pixelsV()) + BLOCK_SIZE, pvopcRef, x, y,
(iMVX & 3) ? ((iMVX >> 1) | 1) : (iMVX >> 1),
(iMVY & 6) ? ((iMVY >> 1) | 2) : (iMVY >> 1), botRef);
} else { // rounding control is messed up here
motionComp((PixelC *)pvopcPred->pixelsY(), pvopcRef->pixelsY(), MB_SIZE,
x * 2 + pmv->trueMVHalfPel().x, y * 2 + pmv->trueMVHalfPel().y, 0, prctMVLimit);
motionCompUV((PixelC *)pvopcPred->pixelsU(), (PixelC *)pvopcPred->pixelsV(), pvopcRef, x, y,
(pmv->m_vctTrueHalfPel.x & 3) ? ((pmv->m_vctTrueHalfPel.x >> 1) | 1) :
(pmv->m_vctTrueHalfPel.x >> 1),
(pmv->m_vctTrueHalfPel.y & 3) ? ((pmv->m_vctTrueHalfPel.y >> 1) | 1) :
(pmv->m_vctTrueHalfPel.y >> 1), 0, prctMVLimit);
}
}
Void CVideoObject::motionCompYField (
PixelC* ppxlcPred, // can be either Y or A
const PixelC* ppxlcRefLeftTop, // point to left-top of the frame
CoordI xRef, CoordI yRef // current coordinate system
)
{
CoordI ix, iy;
const PixelC* ppxlcRef = ppxlcRefLeftTop +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -