📄 shpenc.cpp
字号:
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++) {
Int iSrc = rgiSubBlkIndxSrc [iSubBlk];
Int iDst = rgiSubBlkIndxDst [iSubBlk];
for (CoordI iY = 0; iY < 4; iY++) {
for (CoordI iX = 0; iX < 4; iX++) {
iError += abs (rgppxlcSrc [iSrc] - rgppxlcDst [iDst]);
iSrc++;
iDst++;
}
if (iError > m_volmd.iBinaryAlphaTH)
return TRUE;
iSrc += iSizeSrc - 4;
iDst += iSizeDst - 4;
}
}
return FALSE;
}
UInt CVideoObjectEncoder::encodeCAEIntra (ShapeMode shpmd, CAEScanDirection shpdir)
{
assert (shpmd == INTRA_CAE);
// m_pbitstrmOut->trace (m_rgiCurrShp, TOTAL_BAB_SQUARE_SIZE, "MB_BAB");
UInt nBits = 0;
nBits += codeCrAndSt (shpdir, m_iInverseCR);
//the real arithmatic encoding
StartArCoder (m_parcodec);
if (shpdir == HORIZONTAL) {
const PixelC* ppxlcSrcRow = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
for (Int iRow = BAB_BORDER; iRow < m_iWidthCurrBAB - BAB_BORDER; iRow++) {
const PixelC* ppxlcSrc = ppxlcSrcRow;
for (Int iCol = BAB_BORDER; iCol < m_iWidthCurrBAB - BAB_BORDER; iCol++) {
Int iContext = contextIntra (ppxlcSrc);
#ifdef __TRACE_AND_STATS_
// m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
#endif // __TRACE_AND_STATS_
ArCodeSymbol ((*ppxlcSrc == OPAQUE), gCAEintraProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
ppxlcSrc++;
}
ppxlcSrcRow += m_iWidthCurrBAB;
}
}
else {
const PixelC* ppxlcSrcCol = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
for (Int iCol = BAB_BORDER; iCol < m_iWidthCurrBAB - BAB_BORDER; iCol++) {
const PixelC* ppxlcSrc = ppxlcSrcCol;
for (Int iRow = BAB_BORDER; iRow < m_iWidthCurrBAB - BAB_BORDER; iRow++) {
Int iContext = contextIntraTranspose (ppxlcSrc);
#ifdef __TRACE_AND_STATS_
//m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
#endif // __TRACE_AND_STATS_
ArCodeSymbol ((*ppxlcSrc == OPAQUE), gCAEintraProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
ppxlcSrc += m_iWidthCurrBAB ;
}
ppxlcSrcCol++;
}
}
StopArCoder (m_parcodec, m_pbitstrmShapeMBOut);
nBits += m_parcodec->nBits;
return nBits;
}
UInt CVideoObjectEncoder::encodeCAEInter (ShapeMode shpmd, CAEScanDirection shpdir)
{
assert (shpmd == INTER_CAE_MVDNZ || shpmd == INTER_CAE_MVDZ);
// m_pbitstrmOut->trace (m_rgiCurrShp, TOTAL_BAB_SQUARE_SIZE, "MB_BAB");
UInt nBits = 0;
nBits += codeCrAndSt (shpdir, m_iInverseCR);
const PixelC *ppxlcPredBAB = m_puciPredBAB->pixels();
Int iSizeMB = m_iWidthCurrBAB-BAB_BORDER*2;
Int iSizePredBAB = iSizeMB+MC_BAB_BORDER*2;
if(m_iInverseCR==2)
{
downSampleShapeMCPred(ppxlcPredBAB,m_ppxlcPredBABDown2,2);
ppxlcPredBAB = m_ppxlcPredBABDown2;
}
else if(m_iInverseCR==4)
{
downSampleShapeMCPred(ppxlcPredBAB,m_ppxlcPredBABDown4,4);
ppxlcPredBAB = m_ppxlcPredBABDown4;
}
//the real arithmatic encoding
StartArCoder (m_parcodec);
if (shpdir == HORIZONTAL) {
const PixelC* ppxlcSrcRow = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
const PixelC* ppxlcPredRow = ppxlcPredBAB + iSizePredBAB * MC_BAB_BORDER + MC_BAB_BORDER;
for (Int iRow = 0; iRow < iSizeMB; iRow++) {
const PixelC* ppxlcSrc = ppxlcSrcRow;
const PixelC* ppxlcPred = ppxlcPredRow;
for (Int iCol = 0; iCol < iSizeMB; iCol++) {
Int iContext = contextInter (ppxlcSrc, ppxlcPred);
#ifdef __TRACE_AND_STATS_
//m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
#endif // __TRACE_AND_STATS_
ArCodeSymbol ((*ppxlcSrc == OPAQUE), gCAEinterProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
ppxlcSrc++;
ppxlcPred++;
}
ppxlcSrcRow += m_iWidthCurrBAB;
ppxlcPredRow += iSizePredBAB;
}
}
else {
const PixelC* ppxlcSrcCol = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
const PixelC* ppxlcPredCol = ppxlcPredBAB + iSizePredBAB * MC_BAB_BORDER + MC_BAB_BORDER;
for (Int iCol = 0; iCol < iSizeMB; iCol++) {
const PixelC* ppxlcSrc = ppxlcSrcCol;
const PixelC* ppxlcPred = ppxlcPredCol;
for (Int iRow = 0; iRow < iSizeMB; iRow++) {
Int iContext = contextInterTranspose (ppxlcSrc, ppxlcPred);
#ifdef __TRACE_AND_STATS_
//m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
#endif // __TRACE_AND_STATS_
ArCodeSymbol ((*ppxlcSrc == OPAQUE), gCAEinterProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
ppxlcSrc += m_iWidthCurrBAB;
ppxlcPred += iSizePredBAB;
}
ppxlcSrcCol++;
ppxlcPredCol++;
}
}
StopArCoder (m_parcodec, m_pbitstrmShapeMBOut);
nBits += m_parcodec->nBits;
return nBits;
}
UInt CVideoObjectEncoder::encodeMVDS (CMotionVector mvBYD)
{
assert (!mvBYD.isZero());
m_pentrencSet->m_pentrencShapeMV1->attachStream(*m_pbitstrmShapeMBOut);
m_pentrencSet->m_pentrencShapeMV2->attachStream(*m_pbitstrmShapeMBOut);
UInt nBits = 0;
nBits += m_pentrencSet->m_pentrencShapeMV1->encodeSymbol (abs (mvBYD.iMVX), "MB_SHP_MVDX");
if (mvBYD.iMVX != 0) {
m_pbitstrmShapeMBOut->putBits (signOf(mvBYD.iMVX), (UInt) 1, "MB_SHP_MVDX_Sign");
nBits++;
nBits += m_pentrencSet->m_pentrencShapeMV1->encodeSymbol (abs (mvBYD.iMVY), "MB_SHP_MVDY");
}
else
nBits += m_pentrencSet->m_pentrencShapeMV2->encodeSymbol (abs (mvBYD.iMVY) - 1, "MB_SHP_MVDY");
if (mvBYD.iMVY != 0) {
m_pbitstrmShapeMBOut->putBits (signOf(mvBYD.iMVY), (UInt) 1, "MB_SHP_MVDY_Sign");
nBits++;
}
m_pentrencSet->m_pentrencShapeMV1->attachStream(*m_pbitstrmOut);
m_pentrencSet->m_pentrencShapeMV2->attachStream(*m_pbitstrmOut);
return nBits;
}
Bool CVideoObjectEncoder::sameBlockTranspStatus (const CMBMode* pmbmd, PixelC pxlcRecon) //assume src is 16 x 16 buffer
{
if (pxlcRecon == opaqueValue)
return ((pmbmd->m_rgTranspStatus [Y_BLOCK1] != ALL) && //if recon is all opaque
(pmbmd->m_rgTranspStatus [Y_BLOCK2] != ALL) && //then each orig. blk has to be not all transp
(pmbmd->m_rgTranspStatus [Y_BLOCK3] != ALL) &&
(pmbmd->m_rgTranspStatus [Y_BLOCK4] != ALL));
return TRUE;
}
Bool CVideoObjectEncoder::sameBlockTranspStatus (const CMBMode* pmbmd, const PixelC* pxlcRecon, Int iSizeRecon) //src: 16x16 Recon: 18 x 18 || 20 x 20
{
Int iBorder = (iSizeRecon == 18) ? 1 : 2;
const PixelC* ppxlcBlk1 = pxlcRecon + iBorder + iBorder * iSizeRecon;
const PixelC* ppxlcBlk2 = ppxlcBlk1 + BLOCK_SIZE;
const PixelC* ppxlcBlk3 = pxlcRecon + iSizeRecon * iSizeRecon / 2 + iBorder;
const PixelC* ppxlcBlk4 = ppxlcBlk3 + BLOCK_SIZE;
static rgnOpaquePixels [4];
rgnOpaquePixels [0] = rgnOpaquePixels [1] = rgnOpaquePixels [2] = rgnOpaquePixels [3] = 0;
CoordI ix, iy;
for (iy = 0; iy < BLOCK_SIZE; iy++) {
for (ix = 0; ix < BLOCK_SIZE; ix++) {
rgnOpaquePixels [0] += ppxlcBlk1 [ix];
rgnOpaquePixels [1] += ppxlcBlk2 [ix];
rgnOpaquePixels [2] += ppxlcBlk3 [ix];
rgnOpaquePixels [3] += ppxlcBlk4 [ix];
}
ppxlcBlk1 += iSizeRecon;
ppxlcBlk2 += iSizeRecon;
ppxlcBlk3 += iSizeRecon;
ppxlcBlk4 += iSizeRecon;
}
Int iBlk;
for (iBlk = Y_BLOCK1; iBlk <= Y_BLOCK4; iBlk++)
if (pmbmd->m_rgTranspStatus [iBlk] == ALL) //if org. blk is all transp, the recon can be otherwise
if (rgnOpaquePixels [iBlk - 1] != 0)
return FALSE;
return TRUE;
}
UInt CVideoObjectEncoder::codeCrAndSt (CAEScanDirection shpdir, Int iInverseCR)
{
UInt nBits = 0;
if (m_volmd.bNoCrChange == FALSE) {
UInt nBitsCR = (iInverseCR == 1) ? 1 : 2;
Int iCode = (iInverseCR == 1) ? 0 : (iInverseCR == 2) ? 2 : 3;
m_pbitstrmShapeMBOut->putBits (iCode, nBitsCR, "MB_CR");
nBits += nBitsCR;
}
//Scan direction
m_pbitstrmShapeMBOut->putBits ((shpdir == HORIZONTAL) ? 1 : 0, (UInt) 1, "MB_ST");
nBits++;
return nBits;
}
Void CVideoObjectEncoder::copyReconShapeToRef (PixelC* ppxlcRefFrm, PixelC pxlcSrc) //no need to reset MB buffer
{
for (Int i = 0; i < MB_SIZE; i++) {
pxlcmemset (ppxlcRefFrm, pxlcSrc, MB_SIZE);
ppxlcRefFrm+= m_iFrameWidthY;
}
}
Void CVideoObjectEncoder::copyReconShapeToRef (PixelC* ppxlcRefFrm,
const PixelC* ppxlcSrc, Int iSrcWidth, Int iBorder)
{
ppxlcSrc += iSrcWidth * iBorder + iBorder;
Int iUnit = sizeof(PixelC); // NBIT: for memcpy
for (Int i = 0; i < MB_SIZE; i++) {
memcpy (ppxlcRefFrm, ppxlcSrc, MB_SIZE*iUnit);
ppxlcRefFrm += m_iFrameWidthY;
ppxlcSrc += iSrcWidth;
}
}
Int CVideoObjectEncoder::sadForShape (const PixelC* ppxlcRefBY) const
{
Int iInitSAD = 0;
CoordI ix, iy;
const PixelC* ppxlcCurrBY = m_ppxlcCurrMBBY;
for (iy = 0; iy < MB_SIZE; iy++) {
for (ix = 0; ix < MB_SIZE; ix++)
iInitSAD += abs (ppxlcCurrBY [ix] - ppxlcRefBY [ix]);
ppxlcCurrBY += MB_SIZE;
ppxlcRefBY += m_iFrameWidthY;
}
return iInitSAD;
}
Void CVideoObjectEncoder::blkmatchForShape (
CVOPU8YUVBA* pvopcRefQ,
CMotionVector* pmv,
const CVector& mvPredHalfPel,
CoordI iX, CoordI iY
)
{
Int mbDiff;
CoordI x = iX + (mvPredHalfPel.x >> 1), y = iY + (mvPredHalfPel.y >> 1);
Int iXDest = x, iYDest = y;
CoordI ix, iy;
const PixelC* ppxlcRefMBY = pvopcRefQ->pixelsBY () + m_rctRefFrameY.offset (x, y);
Int iMinSAD = sadForShape (ppxlcRefMBY);
pmv->iMVX = pmv->iMVY = 0;
Int uiPosInLoop, iLoop;
// Spiral Search for the rest
for (iLoop = 1; iLoop <= 16; iLoop++) {
x++;
y++;
ppxlcRefMBY += m_iFrameWidthY + 1;
for (uiPosInLoop = 0; uiPosInLoop < (iLoop << 3); uiPosInLoop++) {
// inside each spiral loop
if (
x >= m_rctRefVOPY0.left && y >= m_rctRefVOPY0.top &&
x <= m_rctRefVOPY0.right - MB_SIZE && y <= m_rctRefVOPY0.bottom - MB_SIZE
) {
const PixelC* ppxlcTmpC = m_ppxlcCurrMBBY;
const PixelC* ppxlcRefMB = ppxlcRefMBY;
mbDiff = 0;
for (iy = 0; iy < MB_SIZE; iy++) {
for (ix = 0; ix < MB_SIZE; ix++)
mbDiff += abs (ppxlcTmpC [ix] - ppxlcRefMB [ix]);
if (mbDiff >= iMinSAD)
goto NEXT_POSITION; // skip the current position
ppxlcRefMB += m_iFrameWidthY;
ppxlcTmpC += MB_SIZE;
}
iMinSAD = mbDiff;
iXDest = x;
iYDest = y;
}
NEXT_POSITION:
if (uiPosInLoop < (iLoop << 1)) {
ppxlcRefMBY--;
x--;
}
else if (uiPosInLoop < (iLoop << 2)) {
ppxlcRefMBY -= m_iFrameWidthY;
y--;
}
else if (uiPosInLoop < (iLoop * 6)) {
ppxlcRefMBY++;
x++;
}
else {
ppxlcRefMBY += m_iFrameWidthY;
y++;
}
}
}
*pmv = CMotionVector (iXDest - iX, iYDest - iY);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -