📄 shpenc.cpp
字号:
UInt nBitsMV=0;
UInt nBitsModeInter = codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
if(pmbmd->m_shpmd==INTER_CAE_MVDNZ)
nBitsMV = encodeMVDS (mvBYD);
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_CAE_INTER_VERTICAL_CODING (TRIAL)");
#endif // __TRACE_AND_STATS_
UInt nBitsVInter = encodeCAEInter (pmbmd->m_shpmd, VERTICAL);
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_CAE_INTER_HORIZONTAL_CODING (TRIAL)");
#endif // __TRACE_AND_STATS_
UInt nBitsHInter = encodeCAEInter (pmbmd->m_shpmd, HORIZONTAL);
UInt nBitsInter = nBitsModeInter + nBitsMV + min (nBitsVInter, nBitsHInter);
m_pbitstrmShapeMBOut->gotoBookmark ();
if (nBitsInter < nBitsIntra)
{
// choose inter coding
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_CAE_INTER_CODING (REAL)");
m_pbitstrmOut->trace (mvShapeMVP, "MB_SHP_MV_PRED (half pel)");
m_pbitstrmOut->trace (*pmvBY, "MB_SHP_MV (half pel)");
m_pbitstrmOut->trace (mvBYD, "MB_SHP_MVD (half pel)");
#endif // __TRACE_AND_STATS_
codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
if(pmbmd->m_shpmd==INTER_CAE_MVDNZ)
encodeMVDS (mvBYD);
if(nBitsVInter<nBitsHInter)
encodeCAEInter (pmbmd->m_shpmd, VERTICAL);
else
encodeCAEInter (pmbmd->m_shpmd, HORIZONTAL);
return nBitsInter;
}
else
{
// choose intra coding
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_CAE_INTRA_CODING (REAL)");
#endif // __TRACE_AND_STATS_
pmvBY->iMVX = NOT_MV;
pmvBY->iMVY = NOT_MV;
pmbmd->m_shpmd = INTRA_CAE;
codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
if(nBitsVIntra<nBitsHIntra)
encodeCAEIntra (pmbmd->m_shpmd, VERTICAL);
else
encodeCAEIntra (pmbmd->m_shpmd, HORIZONTAL);
return nBitsIntra;
}
}
case MVDZ_NOUPDT:
case MVDNZ_NOUPDT:
{
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_CAE_INTER_CODING_NO_UPDATE");
m_pbitstrmOut->trace (mvShapeMVP, "MB_SHP_MV_PRED (half pel)");
m_pbitstrmOut->trace (*pmvBY, "MB_SHP_MV (half pel)");
m_pbitstrmOut->trace (mvBYD, "MB_SHP_MVD (half pel)");
#endif // __TRACE_AND_STATS_
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, m_puciPredBAB->pixels (), MC_BAB_SIZE, MC_BAB_BORDER);
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ((PixelC *)m_puciPredBAB->pixels(), MC_BAB_SIZE, MC_BAB_SIZE, "MB_MC_PRED_BAB");
#endif // __TRACE_AND_STATS_
Int nBits = codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
if(pmbmd->m_shpmd==MVDNZ_NOUPDT)
nBits += encodeMVDS (mvBYD);
return nBits;
}
default:
assert(FALSE);
return 0;
}
}
UInt CVideoObjectEncoder::codeShapeModeIntra (ShapeMode shpmd, const CMBMode* pmbmd, Int iMBX, Int iMBY)
{
UInt nBits = 0;
assert (shpmd == ALL_TRANSP || shpmd == ALL_OPAQUE || shpmd == INTRA_CAE);
static Int iLeftTopMostMB = 0;
Int iRightMostMB = m_iNumMBX - 1;
//get previous shape codes;
Bool bLeftBndry, bRightTopBndry, bTopBndry, bLeftTopBndry;
Int iMBnum = VPMBnum(iMBX, iMBY);
bLeftBndry = bVPNoLeft(iMBnum, iMBX);
bTopBndry = bVPNoTop(iMBnum);
bRightTopBndry = bVPNoRightTop(iMBnum, iMBX);
bLeftTopBndry = bVPNoLeftTop(iMBnum, iMBX);
ShapeMode shpmdTop = ALL_TRANSP;
ShapeMode shpmdTopRight = ALL_TRANSP;
ShapeMode shpmdTopLeft = ALL_TRANSP;
ShapeMode shpmdLeft = ALL_TRANSP;
// Modified for error resilient mode by Toshiba(1997-11-14)
if (!bTopBndry)
shpmdTop = (pmbmd - m_iNumMBX)->m_shpmd;
if (!bRightTopBndry)
shpmdTopRight = (pmbmd - m_iNumMBX + 1)->m_shpmd;
if (!bLeftBndry)
shpmdLeft = (pmbmd - 1)->m_shpmd;
if (!bLeftTopBndry)
shpmdTopLeft = (pmbmd - m_iNumMBX - 1)->m_shpmd;
//if (iMBY > iLeftTopMostMB) {
// shpmdTop = (pmbmd - m_iNumMBX)->m_shpmd;
// if (iMBX < iRightMostMB)
// shpmdTopRight = (pmbmd - m_iNumMBX + 1)->m_shpmd;
//}
//if (iMBX > iLeftTopMostMB) {
// shpmdLeft = (pmbmd - 1)->m_shpmd;
// if (iMBY > iLeftTopMostMB)
// shpmdTopLeft = (pmbmd - m_iNumMBX - 1)->m_shpmd;
//}
// End Toshiba(1997-11-14)
assert (shpmdTop != UNKNOWN && shpmdTopRight != UNKNOWN &&
shpmdTopLeft != UNKNOWN && shpmdLeft != UNKNOWN);
//get code and its size
UInt uiTblIndex = shpmdTopLeft * 81 + shpmdTop * 27 +
shpmdTopRight * 9 + shpmdLeft * 3 + shpmd;
assert (uiTblIndex >= 0 && uiTblIndex < 243);
assert (grgchFirstShpCd [uiTblIndex] == 0 || grgchFirstShpCd [uiTblIndex] == 2 ||
grgchFirstShpCd [uiTblIndex] == 3);
// Modified for error resilient mode by Toshiba(1997-11-14)
UInt nCodeSize = (grgchFirstShpCd [uiTblIndex] == 0) ? 1
: grgchFirstShpCd [uiTblIndex];
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ((Int) shpmd, "MB_Curr_ShpMd");
#endif // __TRACE_AND_STATS_
m_pbitstrmShapeMBOut->putBits ((Int) 1, nCodeSize, "MB_Shape_Mode");
// End Toshiba(1997-11-14)
nBits += nCodeSize;
return nBits;
}
UInt CVideoObjectEncoder::codeShapeModeInter (const ShapeMode& shpmd, const ShapeMode& shpmdColocatedMB)
{
assert (shpmdColocatedMB != UNKNOWN && shpmd != UNKNOWN);
UInt nBits = 0;
CEntropyEncoder* pentrenc = m_pentrencSet->m_ppentrencShapeMode [shpmdColocatedMB];
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ((Int) shpmdColocatedMB, "MB_Colocated_ShpMd");
m_pbitstrmOut->trace ((Int) shpmd, "MB_Curr_ShpMd");
#endif // __TRACE_AND_STATS_
pentrenc->attachStream(*m_pbitstrmShapeMBOut);
nBits += pentrenc->encodeSymbol (shpmd, "MB_Shape_Mode");
pentrenc->attachStream(*m_pbitstrmOut);
return nBits;
}
// find appropriate size for coded babs
ShapeMode CVideoObjectEncoder::round (PixelC* ppxlcSrcFrm, const CMBMode* pmbmd) //only to partial BABs
{
ShapeMode shpmd;
Bool bIsErrorLarge;
if (m_volmd.bNoCrChange == FALSE)
{
// attempt to reduce bab size
m_bNoShapeChg = FALSE;
static iThreshD4 = 7 * OPAQUE;
// reduce by factor 4
downSampleShape (m_ppxlcCurrMBBY,
m_rgiSubBlkIndx16x16,
m_ppxlcCurrMBBYDown4,
m_rgiPxlIndx8x8,
4, iThreshD4, 16);
// see if this size is acceptable
shpmd = INTRA_CAE;
m_iInverseCR = 4;
m_iWidthCurrBAB = 8;
// subsample border before upsample to original size
subsampleLeftTopBorderFromVOP (ppxlcSrcFrm, m_ppxlcCurrMBBYDown4);
makeRightBottomBorder (m_ppxlcCurrMBBYDown4, 8);
upSampleShape(ppxlcSrcFrm,m_ppxlcCurrMBBYDown4,m_ppxlcReconCurrBAB);
// check if approximation is acceptable
bIsErrorLarge = isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
m_ppxlcReconCurrBAB, m_rgiSubBlkIndx20x20, 20, pmbmd);
if(!bIsErrorLarge)
{
// ok, so assign encoding buffer
m_rgpxlcCaeSymbol = m_ppxlcCurrMBBYDown4;
return shpmd;
}
static iThreshD2 = OPAQUE;
// factor 4 failed, so try to reduce by factor 2
downSampleShape (m_ppxlcCurrMBBY,
m_rgiSSubBlkIndx16x16,
m_ppxlcCurrMBBYDown2,
m_rgiPxlIndx12x12,
2, iThreshD2, 64);
// mixed, so see if this size is acceptable
shpmd = INTRA_CAE;
m_iInverseCR = 2;
m_iWidthCurrBAB = 12;
// subsample border before upsample to original size
subsampleLeftTopBorderFromVOP (ppxlcSrcFrm, m_ppxlcCurrMBBYDown2);
makeRightBottomBorder (m_ppxlcCurrMBBYDown2, 12);
upSampleShape(ppxlcSrcFrm,m_ppxlcCurrMBBYDown2, m_ppxlcReconCurrBAB);
// check if approximation is acceptable
bIsErrorLarge = isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
m_ppxlcReconCurrBAB, m_rgiSubBlkIndx20x20, 20, pmbmd);
if(!bIsErrorLarge)
{
// ok, so assign encoding buffer
m_rgpxlcCaeSymbol = m_ppxlcCurrMBBYDown2;
return shpmd;
}
}
// has to be original size
m_bNoShapeChg = TRUE;
shpmd = INTRA_CAE;
m_iInverseCR = 1;
m_iWidthCurrBAB = BAB_SIZE;
// copy data to ReconCurrBAB
PixelC* ppxlcDst = m_ppxlcReconCurrBAB + BAB_BORDER + BAB_BORDER * TOTAL_BAB_SIZE;
PixelC* ppxlcSrc = m_ppxlcCurrMBBY;
Int iUnit = sizeof(PixelC); // NBIT: for memcpy
Int i;
for (i = 0; i < MB_SIZE; i++) {
memcpy (ppxlcDst, ppxlcSrc, MB_SIZE*iUnit);
ppxlcSrc += MB_SIZE;
ppxlcDst += BAB_SIZE;
}
// make borders
copyLeftTopBorderFromVOP (ppxlcSrcFrm, m_ppxlcReconCurrBAB);
makeRightBottomBorder (m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE);
// assign encoding buffer
m_rgpxlcCaeSymbol = m_ppxlcReconCurrBAB;
return shpmd;
}
Int CVideoObjectEncoder::downSampleShape (const PixelC* ppxlcSrc,
Int* rgiSrcSubBlk,
PixelC* ppxlcDst,
Int* piDstPxl,
Int iRate,
Int iThreshold,
Int nSubBlk)
{
Int nOpaquePixel = 0, iSum = 0;
Int iSubBlk;
for (iSubBlk = 0; iSubBlk < nSubBlk; iSubBlk++) {
Int i = rgiSrcSubBlk [iSubBlk];
iSum = 0;
for (CoordI iY = 0; iY < iRate; iY++) {
for (CoordI iX = 0; iX < iRate; iX++) {
iSum += abs (ppxlcSrc [i++]); //abs???
}
i += MB_SIZE - iRate;
}
ppxlcDst [*piDstPxl] = (iSum > iThreshold) ? OPAQUE : TRANSPARENT;
nOpaquePixel += ppxlcDst [*piDstPxl];
piDstPxl++;
}
return (nOpaquePixel /= OPAQUE);
}
Bool CVideoObjectEncoder::isErrorLarge (const PixelC* rgppxlcSrc, const Int* rgiSubBlkIndx, Int iWidthSrc, PixelC pxlcRecon, const CMBMode* pmbmd)
{
if (pmbmd->m_bhas4MVForward == TRUE) {
if (!sameBlockTranspStatus (pmbmd, pxlcRecon))
return TRUE;
}
//check error in each 4x4 subblock
Int iSubBlk;
Int iError = 0;
for (iSubBlk = 0; iSubBlk < 16; iSubBlk++) {
Int i = rgiSubBlkIndx [iSubBlk];
for (CoordI iY = 0; iY < 4; iY++) {
for (CoordI iX = 0; iX < 4; iX++) {
iError += abs (rgppxlcSrc [i++] - pxlcRecon);
}
if (iError > m_volmd.iBinaryAlphaTH)
return TRUE;
i += iWidthSrc - 4;
}
}
return FALSE;
}
Bool CVideoObjectEncoder::isErrorLarge (const PixelC* rgppxlcSrc, const Int* rgiSubBlkIndxSrc, const Int iSizeSrc,
const PixelC* rgppxlcDst, const Int* rgiSubBlkIndxDst, const Int iSizeDst, const CMBMode* pmbmd)
{
if (pmbmd->m_bhas4MVForward == TRUE) {
if (!sameBlockTranspStatus (pmbmd, rgppxlcDst, iSizeDst))
return TRUE;
}
//check error in each 4x4 subblock
Int iSubBlk;
Int iError = 0;
for (iSubBlk = 0; iSubBlk < 16; iSubBlk++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -