📄 vopseenc.cpp
字号:
CVideoObjectEncoder::CVideoObjectEncoder (
UInt uiVOId,
VOLMode& volmd,
VOPMode& vopmd,
Int iSessionWidth,
Int iSessionHeight
) :
CVideoObject (),
m_pvopcOrig (NULL),
m_rgiSubBlkIndx16x16 (NULL),
m_rgiSSubBlkIndx16x16 (NULL),
m_rgiSubBlkIndx18x18 (NULL),
m_rgiSubBlkIndx20x20 (NULL),
m_rgiPxlIndx12x12 (NULL),
m_rgiPxlIndx8x8 (NULL)
{
// sprite stuff
m_uiSprite = 0; // sprite off
m_pchBitsBuffer = NULL;
m_pbitstrmOut = NULL;
m_pentrencSet = NULL;
// shape cache
m_pchShapeBitsBuffer = NULL;
m_pbitstrmShape = NULL;
m_pbitstrmShapeMBOut = NULL;
m_uiVOId = uiVOId;
m_volmd = volmd;
m_vopmd = vopmd;
// decideMVInfo ();
m_vopmd.iRoundingControl = 0;
m_vopmd.iRoundingControlEncSwitch = 0;
Int iMod = iSessionWidth % MB_SIZE;
Int iSessionWidthRound = (iMod > 0) ? iSessionWidth + MB_SIZE - iMod : iSessionWidth;
iMod = iSessionHeight % MB_SIZE;
Int iSessionHeightRound = (iMod > 0) ? iSessionHeight + MB_SIZE - iMod : iSessionHeight;
m_rctRefFrameY = CRct (
-EXPANDY_REF_FRAME, -EXPANDY_REF_FRAME,
EXPANDY_REF_FRAME + iSessionWidthRound, EXPANDY_REF_FRAME + iSessionHeightRound
);
m_rctRefFrameUV = m_rctRefFrameY.downSampleBy2 ();
m_pvopcOrig = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
m_pvopcRefOrig0 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
m_pvopcRefOrig1 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
allocateVOLMembers (iSessionWidth, iSessionHeight);
CRct rctFrameZoom = m_rctRefFrameY.upSampleBy2 ();
m_puciRefQZoom0 = new CU8Image (rctFrameZoom);
m_puciRefQZoom1 = new CU8Image (rctFrameZoom);
m_pfdct = new CFwdBlockDCT;
// B-VOP MB buffer
m_puciDirectPredMB = new CU8Image (CRct (0, 0, MB_SIZE, MB_SIZE));
m_puciInterpPredMB = new CU8Image (CRct (0, 0, MB_SIZE, MB_SIZE));
m_ppxlcDirectPredMBY = (PixelC*) m_puciDirectPredMB->pixels ();
m_ppxlcInterpPredMBY = (PixelC*) m_puciInterpPredMB->pixels ();
m_piiDirectErrorMB = new CIntImage (CRct (0, 0, MB_SIZE, MB_SIZE));
m_piiInterpErrorMB = new CIntImage (CRct (0, 0, MB_SIZE, MB_SIZE));
m_ppxliDirectErrorMBY = (PixelI*) m_piiDirectErrorMB->pixels ();
m_ppxliInterpErrorMBY = (PixelI*) m_piiInterpErrorMB->pixels ();
// with shape
if (m_volmd.fAUsage != RECTANGLE) {
m_rgiSubBlkIndx16x16 = computeShapeSubBlkIndex (4, 16);
m_rgiSSubBlkIndx16x16 = computeShapeSubBlkIndex (2, 16);
m_rgiSubBlkIndx18x18 = computeShapeSubBlkIndex (4, 18);
m_rgiSubBlkIndx20x20 = computeShapeSubBlkIndex (4, 20);
m_rgiPxlIndx12x12 = new Int [8 * 8];
Int* piPxl = m_rgiPxlIndx12x12;
UInt i, j;
for (i = 2; i < 10; i++)
for (j = 2; j < 10; j++)
*piPxl++ = i * 12 + j;
m_rgiPxlIndx8x8 = new Int [4 * 4];
piPxl = m_rgiPxlIndx8x8;
for (i = 2; i < 6; i++)
for (j = 2; j < 6; j++)
*piPxl++ = i * 8 + j;
}
m_statRC.resetSkipMode ();
m_rgdSNR = (m_volmd.fAUsage == EIGHT_BIT) ? new Double [4] : new Double [3];
// some fixed variables
m_iFrameWidthZoomY = m_iFrameWidthY * 2;
m_iFrameWidthZoomUV = m_iFrameWidthUV * 2;
m_iFrameWidthZoomYx2Minus2MB = m_iFrameWidthY * 2 * 2 - 2 * MB_SIZE;
m_iFrameWidthZoomYx2Minus2Blk = m_iFrameWidthY * 2 * 2 - 2 * BLOCK_SIZE;
if (m_volmd.fAUsage == RECTANGLE) {
m_rctCurrVOPY = CRct (0, 0, iSessionWidthRound, iSessionHeightRound);
m_pvopcOrig->setBoundRct (m_rctCurrVOPY);
m_rctCurrVOPUV = m_rctCurrVOPY.downSampleBy2 ();
m_rctRefVOPY0 = m_rctCurrVOPY;
m_rctRefVOPY0.expand (EXPANDY_REFVOP);
m_rctRefVOPUV0 = m_rctRefVOPY0.downSampleBy2 ();
m_rctRefVOPY1 = m_rctRefVOPY0;
m_rctRefVOPUV1 = m_rctRefVOPUV0;
m_rctRefVOPZoom0 = m_rctRefVOPY0.upSampleBy2 ();
m_pvopcRefOrig0->setBoundRct (m_rctRefVOPY0);
m_pvopcRefOrig1->setBoundRct (m_rctRefVOPY1);
computeVOLConstMembers (); // these VOP members are the same for all frames
}
}
Bool CVideoObjectEncoder::skipTest(Time t,VOPpredType vopPredType)
{
if (m_uiRateControl==RC_MPEG4) {
if (!m_statRC.firstFrame ()) {// test whether we should skip this frame
if (m_statRC.skipThisFrame ())
return TRUE;
}
else
m_statRC.resetFirstFrame ();
}
return FALSE;
}
Void CVideoObjectEncoder::encode (
Bool bVOPVisible,
Time t,
VOPpredType vopPredType,
const CVOPU8YUVBA* pvopfRefBaseLayer)
{
m_t = t;
m_vopmd.vopPredType = vopPredType;
m_statsVOP.reset ();
Bool bTemporalScalability = m_volmd.bTemporalScalability; // added by Sharp (98/2/10)
Bool bPrevRefVopWasCoded = m_bCodedFutureRef;
//__LOW_LATENCY_SPRITE_
if (m_uiSprite == 1 && m_sptMode != BASIC_SPRITE && m_vopmd.SpriteXmitMode != STOP) {
setRefStartingPointers (); // need to compute the starting pointers of the refVOP's (corresponding to the current Rct)
computeVOPMembers ();
m_iNumSptMB = 0;
encodeVOP ();
}
else {
if (m_uiSprite == 1 && m_t>=0)
m_vopmd.vopPredType = SPRITE;
m_pbitstrmOut->reset ();
cout << "\nVOP " << m_uiVOId << "\n";
cout << "\tVOL " << m_volmd.volType << "\n"; // added by Sharp (98/2/10)
if(m_vopmd.vopPredType==IVOP || m_vopmd.vopPredType==PVOP)
m_bCodedFutureRef = bVOPVisible; // flag used by bvop prediction
if(!bVOPVisible)
{
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut -> trace (m_t, "VOP_Time");
#endif // __TRACE_AND_STATS_
codeNonCodedVOPHead ();
cout << "\tTime..." << m_t << " (" << m_t/m_volmd.dFrameHz << " sec)"
<< "\n\tNot coded.\n\n";
cout.flush ();
m_statsVOP.nBitsStuffing += m_pbitstrmOut->flush ();
#ifdef __TRACE_AND_STATS_
m_statsVOP.dSNRY = m_statsVOP.dSNRU = m_statsVOP.dSNRV = 0;
m_statsVOP.print (TRUE);
m_statsVOL += m_statsVOP;
#endif // __TRACE_AND_STATS_
}
if(bPrevRefVopWasCoded) // only swap references if previous vop was coded
{
if (m_volmd.volType == BASE_LAYER)
updateAllRefVOPs (); // update all reconstructed VOP's
else if (!bTemporalScalability) { // modified by Sharp (98/2/10)
if(m_volmd.volType == ENHN_LAYER && m_vopmd.vopPredType == PVOP)
m_vopmd.iRefSelectCode = 3;
else if(m_volmd.volType == ENHN_LAYER && m_vopmd.vopPredType == BVOP)
m_vopmd.iRefSelectCode = 0;
updateAllRefVOPs (pvopfRefBaseLayer); // for spatial scalability
}
if (m_volmd.bOriginalForME) {
if (m_vopmd.vopPredType == PVOP ||
(m_volmd.volType == ENHN_LAYER && m_vopmd.vopPredType == BVOP && m_vopmd.iRefSelectCode == 0))
swapVOPU8Pointers (m_pvopcRefOrig0, m_pvopcRefOrig1);
}
}
if (m_vopmd.vopPredType != BVOP) {
if(bPrevRefVopWasCoded)
{
// swap zoomed ref images
CU8Image *puciTmp = m_puciRefQZoom0;
m_puciRefQZoom0 = m_puciRefQZoom1;
m_puciRefQZoom1 = puciTmp;
m_rctRefVOPZoom0 = m_rctRefVOPZoom1;
}
m_vopmd.iSearchRangeBackward = 0;
if(bPrevRefVopWasCoded)
if ( !bTemporalScalability || m_volmd.volType == BASE_LAYER ) // added by Sharp (99/1/28)
m_tPastRef = m_tFutureRef;
m_tDistanceBetwIPVOP = (m_t - m_tPastRef) / m_volmd.iTemporalRate;
m_tFutureRef = m_t;
m_iBCount = 0;
if(m_vopmd.vopPredType == PVOP &&
m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode ==3)
m_tPastRef = m_t;
if (m_vopmd.vopPredType == PVOP) {
// swap rounding control 0 <-> 1 every coded PVOP
if( bPrevRefVopWasCoded && !m_volmd.bRoundingControlDisable)
m_vopmd.iRoundingControlEncSwitch ^= 0x00000001;
m_vopmd.iRoundingControl = m_vopmd.iRoundingControlEncSwitch;
m_rctRefVOPZoom0 = m_rctRefVOPY0.upSampleBy2 ();
biInterpolateY (m_pvopcRefQ0, m_rctRefVOPY0, m_puciRefQZoom0,
m_rctRefVOPZoom0, m_vopmd.iRoundingControl);
m_vopmd.iSearchRangeForward =
checkrange (m_volmd.iMVRadiusPerFrameAwayFromRef * (m_t - m_tPastRef) / m_volmd.iTemporalRate, 1, 1024);
} else
m_vopmd.iSearchRangeForward = 0;
} else {
// BVOP, set rounding control to zero
m_vopmd.iRoundingControl = 0;
if (m_volmd.volType==ENHN_LAYER && m_vopmd.iRefSelectCode==0){
m_tPastRef = m_tFutureRef;
m_tFutureRef = m_t;
}
m_iBCount++;
if (m_iBCount == 1 || (m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode==0))
{
if(bPrevRefVopWasCoded)
{
m_rctRefVOPZoom1 = m_rctRefVOPY1.upSampleBy2 ();
biInterpolateY (m_pvopcRefQ1,m_rctRefVOPY1,
m_puciRefQZoom1, m_rctRefVOPZoom1, 0);
}
if (m_vopmd.iRoundingControlEncSwitch==1 // modified by Sharp (98/2/10) && // Need to re-compute because iRoundingControl was 1
|| (m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode == 0) || bTemporalScalability)
{
m_rctRefVOPZoom0 = m_rctRefVOPY0.upSampleBy2 ();
biInterpolateY (m_pvopcRefQ0, m_rctRefVOPY0, m_puciRefQZoom0, m_rctRefVOPZoom0, 0);
}
}
//m_vopmd.iSearchRangeForward = 15;
//m_vopmd.iSearchRangeBackward = 15;
m_vopmd.iSearchRangeForward =
checkrange ((m_t - m_tPastRef) * m_volmd.iMVRadiusPerFrameAwayFromRef / m_volmd.iTemporalRate, 1, 1024);
m_vopmd.iSearchRangeBackward =
checkrange ((m_tFutureRef - m_t) * m_volmd.iMVRadiusPerFrameAwayFromRef / m_volmd.iTemporalRate, 1, 1024);
}
decideMVInfo();
m_statsVOP.nVOPs = 1;
if (m_volmd.fAUsage != RECTANGLE)
resetBYPlane ();
if(!bVOPVisible)
{
if (m_vopmd.vopPredType != BVOP
&& m_volmd.fAUsage != RECTANGLE && bPrevRefVopWasCoded)
{
// give the current object a dummy size
m_iNumMBX = m_iNumMBY = m_iNumMB = 1;
saveShapeMode(); // save the previous reference vop shape mode
}
return; // return if not coded
}
// prepare for the current original data
// extend the currVOP size to multiples of MBSize, will put zero on extended pixels
if (m_volmd.fAUsage != RECTANGLE) {
if (m_uiSprite != 1) { // add by cgu to deal with vop-mc-left-top 12/5
findTightBoundingBox ();
findBestBoundingBox ();
} else if (m_sptMode == BASIC_SPRITE) {
Int iSpriteWidth = m_rctSpt.right - m_rctSpt.left;
if(iSpriteWidth%16)
iSpriteWidth += 16 - (iSpriteWidth%16);
Int iSpriteHeight = m_rctSpt.bottom - m_rctSpt.top;
if(iSpriteHeight%16)
iSpriteHeight += 16 - (iSpriteHeight%16);
m_pvopcOrig->setBoundRct (CRct (0, 0, iSpriteWidth, iSpriteHeight));
}
m_rctCurrVOPY = m_pvopcOrig->whereBoundY ();
m_rctCurrVOPUV = m_pvopcOrig->whereBoundUV ();
setRefStartingPointers (); // need to compute the starting pointers of the refVOP's (corresponding to the current Rct)
computeVOPMembers ();
// Modified for error resilient mode by Toshiba(1998-1-16)
if (m_volmd.bVPBitTh < 0 || m_volmd.bShapeOnly==TRUE) {
m_vopmd.bShapeCodingType = (m_vopmd.vopPredType == IVOP) ? 0 : 1;
} else {
m_vopmd.bShapeCodingType = (m_volmd.iBinaryAlphaRR<0)?1:((m_t % m_volmd.iBinaryAlphaRR)==0) ? 0 : 1;
}
// printf("vop_shape_coding_type=%d\n",m_vopmd.bShapeCodingType);
// End Toshiba(1998-1-16)
}
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut -> trace (m_t, "VOP_Time");
#endif // __TRACE_AND_STATS_
codeVOPHead ();
cout << "\t" << "Time..." << m_t << " (" << m_t/m_volmd.dFrameHz << " sec)";
switch(vopPredType)
{
case IVOP:
cout << "\tIVOP";
break;
case PVOP:
cout << "\tPVOP (reference: t=" << m_tPastRef <<")";
break;
case BVOP:
cout << "\tBVOP (past ref: t=" << m_tPastRef
<< ", future ref: t=" << m_tFutureRef <<")";
break;
default:
break;
}
cout << "\n";
cout.flush ();
encodeVOP ();
m_statsVOP.nBitsStuffing += m_pbitstrmOut->flush ();
}
#ifdef __TRACE_AND_STATS_
if (m_vopmd.vopPredType == BVOP)
computeSNRs (m_pvopcCurrQ);
else
computeSNRs (m_pvopcRefQ1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -