📄 shpenc.cpp
字号:
/*************************************************************************
This software module was originally developed by
Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
(April, 1997)
and edited by
Wei Wu (weiwu@stallion.risc.rockwell.com) Rockwell Science Center
and also edited by
Yoshihiro Kikuchi (TOSHIBA CORPORATION)
Takeshi Nagai (TOSHIBA CORPORATION)
Toshiaki Watanabe (TOSHIBA CORPORATION)
Noboru Yamaguchi (TOSHIBA CORPORATION)
and also edited by
Takefumi Nagumo (nagumo@av.crl.sony.co.jp) Sony Corporation
Sehoon Son (shson@unitel.co.kr) Samsung AIT
in the course of development of the MPEG-4 Video (ISO/IEC 14496-2).
This software module is an implementation of a part of one or more MPEG-4 Video tools
as specified by the MPEG-4 Video.
ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications
thereof for use in hardware or software products claiming conformance to the MPEG-4 Video.
Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents.
The original developer of this software module and his/her company,
the subsequent editors and their companies,
and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation.
Copyright is not released for non MPEG-4 Video conforming products.
Microsoft retains full right to use the code for his/her own purpose,
assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products.
This copyright notice must be included in all copies or derivative works.
Copyright (c) 1996, 1997.
Module Name:
shpenc.hpp
Abstract:
binary shape encoder with context-based arithmatic coder
Revision History:
Feb.01 2000: Bug fixed OBSS by Takefumi Nagumo (SONY)
*************************************************************************/
#include "typeapi.h"
#include "entropy/entropy.hpp"
#include "entropy/huffman.hpp"
#include "entropy/bitstrm.hpp"
#include "global.hpp"
#include "mode.hpp"
#include "codehead.h"
#include "cae.h"
#include "vopses.hpp"
#include "vopseenc.hpp"
#include "dct.hpp" // HHI Schueuer: inserted for deriveSADCTRowLengths
//OBSS_SAIT_991015
#include <math.h>
#define SIGN(n) (n>0)?1:((n<0)?-1:0)
//~OBSS_SAIT_991015
#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#endif // __MFC_
// HHI Schueuer: inserted for SADCT
Void CVideoObjectEncoder::deriveSADCTRowLengths(Int **piCoeffWidths, const PixelC* ppxlcMBBY, const PixelC* ppxlcCurrMBBUV,
const TransparentStatus *pTransparentStatus)
{
CFwdSADCT *pfdct = (CFwdSADCT *)m_pfdct;
const PixelC *pSrc;
for (int i=Y_BLOCK1; i<U_BLOCK; i++) {
if (pTransparentStatus[i] != PARTIAL) {
memset(piCoeffWidths[i], 0, BLOCK_SIZE * sizeof(piCoeffWidths[i][0]));
continue;
}
switch (i) {
case Y_BLOCK1:
pSrc = ppxlcMBBY;
break;
case Y_BLOCK2:
pSrc = ppxlcMBBY + BLOCK_SIZE;
break;
case Y_BLOCK3:
pSrc = ppxlcMBBY + BLOCK_SIZE*MB_SIZE;
break;
case Y_BLOCK4:
pSrc = ppxlcMBBY + BLOCK_SIZE*MB_SIZE + BLOCK_SIZE;
break;
}
pfdct->getRowLength(piCoeffWidths[i], pSrc, MB_SIZE);
#ifdef _DEBUG
for (int iy=0; iy<BLOCK_SIZE; iy++) {
int l = *(piCoeffWidths[i] + iy);
assert(l>=0 && l<=BLOCK_SIZE);
}
#endif
}
if (pTransparentStatus[U_BLOCK] == PARTIAL) {
pfdct->getRowLength(piCoeffWidths[U_BLOCK], ppxlcCurrMBBUV, BLOCK_SIZE);
#ifdef _DEBUG
for (int iy=0; iy<BLOCK_SIZE; iy++) {
int l = *(piCoeffWidths[i] + iy);
assert(l>=0 && l<=BLOCK_SIZE);
}
#endif
}
else
memset(piCoeffWidths[U_BLOCK], 0, BLOCK_SIZE * sizeof(piCoeffWidths[i][0]));
#ifdef __TRACE_DECODING_
m_ptrcer->dumpSADCTRowLengths(piCoeffWidths);
#endif
}
// end
Int CVideoObjectEncoder::codeIntraShape (PixelC* ppxlcSrcFrm, CMBMode* pmbmd, Int iMBX, Int iMBY)
{
m_iInverseCR = 1;
m_iWidthCurrBAB = BAB_SIZE;
#ifdef __TRACE_AND_STATS_
if(pmbmd->m_rgTranspStatus [0] == NONE)
m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL OPAQUE");
else if(pmbmd->m_rgTranspStatus [0] == ALL)
m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL TRANSP");
else
m_pbitstrmOut->trace (m_ppxlcCurrMBBY, MB_SIZE, MB_SIZE, "ORIGINAL_BAB");
#endif // __TRACE_AND_STATS_
Int iMBnum = VPMBnum(iMBX, iMBY);
m_bVPNoLeft = bVPNoLeft(iMBnum, iMBX);
m_bVPNoTop = bVPNoTop(iMBnum);
m_bVPNoRightTop = bVPNoRightTop(iMBnum, iMBX);
m_bVPNoLeftTop = bVPNoLeftTop(iMBnum, iMBX);
if (pmbmd->m_rgTranspStatus [0] == NONE)
pmbmd->m_shpmd = ALL_OPAQUE;
else if (pmbmd->m_rgTranspStatus [0] == ALL)
pmbmd->m_shpmd = ALL_TRANSP;
else if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, TRANSPARENT, pmbmd))
{
pmbmd->m_shpmd = ALL_TRANSP;
if ( !isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, OPAQUE, pmbmd))
{
// both opaque and transparent are good, so count pixels to decide
Int i,iSum=0;
for(i=0;i<MB_SQUARE_SIZE;i++)
iSum+=(m_ppxlcCurrMBBY[i]>0);
if(iSum>=(MB_SQUARE_SIZE>>1))
pmbmd->m_shpmd = ALL_OPAQUE;
}
}
else if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, OPAQUE, pmbmd))
pmbmd->m_shpmd = ALL_OPAQUE;
else
pmbmd->m_shpmd = round (ppxlcSrcFrm, pmbmd);
if(pmbmd->m_shpmd==ALL_TRANSP)
{
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_ALL_TRANSP");
#endif // __TRACE_AND_STATS_
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, TRANSPARENT);
return codeShapeModeIntra (ALL_TRANSP, pmbmd, iMBX, iMBY);
}
else if(pmbmd->m_shpmd==ALL_OPAQUE)
{
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_ALL_OPAQUE");
#endif // __TRACE_AND_STATS_
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, OPAQUE);
return codeShapeModeIntra (ALL_OPAQUE, pmbmd, iMBX, iMBY);
}
else
{
// intra CAE
assert(pmbmd->m_shpmd == INTRA_CAE);
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace (m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, TOTAL_BAB_SIZE, "MB_RECON_BAB (Ignore border)");
m_pbitstrmOut->trace (m_rgpxlcCaeSymbol, m_iWidthCurrBAB , m_iWidthCurrBAB , "MB_ENCODED_BAB");
#endif // __TRACE_AND_STATS_
if (m_bNoShapeChg) //must be partial
copyReconShapeToRef (ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
else
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
UInt nBitsMode = codeShapeModeIntra (INTRA_CAE, pmbmd, iMBX, iMBY);
m_pbitstrmShapeMBOut->setBookmark ();
UInt nBitsV = encodeCAEIntra (INTRA_CAE, VERTICAL);
m_pbitstrmShapeMBOut->gotoBookmark ();
UInt nBitsH = encodeCAEIntra (INTRA_CAE, HORIZONTAL);
if (nBitsV < nBitsH)
{
m_pbitstrmShapeMBOut->gotoBookmark ();
nBitsV = encodeCAEIntra (INTRA_CAE, VERTICAL);
return nBitsV+nBitsMode;
}
else
return nBitsH+nBitsMode;
}
}
Int CVideoObjectEncoder::codeInterShape (PixelC* ppxlcSrcFrm,
CVOPU8YUVBA* pvopcRefQ,
CMBMode* pmbmd,
const ShapeMode& shpmdColocatedMB,
const CMotionVector* pmv,
CMotionVector* pmvBY,
CoordI iX, CoordI iY,
Int iMBX, Int iMBY)
{
m_iInverseCR = 1;
m_iWidthCurrBAB = BAB_SIZE;
pmbmd->m_shpmd = UNKNOWN;
CMotionVector mvBYD (0, 0);
CMotionVector mvShapeMVP;
#ifdef __TRACE_AND_STATS_
if(pmbmd->m_rgTranspStatus [0] == NONE)
m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL OPAQUE");
else if(pmbmd->m_rgTranspStatus [0] == ALL)
m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL TRANSP");
else
m_pbitstrmOut->trace (m_ppxlcCurrMBBY, MB_SIZE, MB_SIZE, "ORIGINAL_BAB");
#endif // __TRACE_AND_STATS_
Int iMBnum = VPMBnum(iMBX, iMBY);
m_bVPNoLeft = bVPNoLeft(iMBnum, iMBX);
m_bVPNoTop = bVPNoTop(iMBnum);
m_bVPNoRightTop = bVPNoRightTop(iMBnum, iMBX);
m_bVPNoLeftTop = bVPNoLeftTop(iMBnum, iMBX);
if (pmbmd->m_rgTranspStatus [0] == ALL)
pmbmd->m_shpmd = ALL_TRANSP;
else if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, TRANSPARENT, pmbmd))
{
pmbmd->m_shpmd = ALL_TRANSP;
if ( !isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, OPAQUE, pmbmd))
{
// both opaque and transparent are good, so count pixels to decide
Int i,iSum=0;
for(i=0;i<MB_SQUARE_SIZE;i++)
iSum+=(m_ppxlcCurrMBBY[i]>0);
if(iSum>=(MB_SQUARE_SIZE>>1))
pmbmd->m_shpmd = ALL_OPAQUE;
}
}
else if(pmbmd->m_rgTranspStatus [0] == NONE)
pmbmd->m_shpmd = ALL_OPAQUE;
else if(!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, OPAQUE, pmbmd))
pmbmd->m_shpmd = ALL_OPAQUE;
if(pmbmd->m_shpmd!=ALL_TRANSP )
{
// find motion vectors
//OBSSFIX_MODE3
if( m_volmd.volType == ENHN_LAYER && m_volmd.bSpatialScalability == 1 && m_volmd.iHierarchyType == 0 &&
m_volmd.iEnhnType != 0 && m_volmd.iuseRefShape == 1 && m_vopmd.vopPredType == PVOP){
//Set predictor of Shape coding of OBSS (simulcast shape case)
mvShapeMVP.setToZero();
memset((void *)m_puciPredBAB->pixels(),255, MC_BAB_SIZE*MC_BAB_SIZE);
}else{
mvShapeMVP = findShapeMVP (pmv, pmvBY, pmbmd, iMBX, iMBY);
assert (mvShapeMVP.iMVX != NOT_MV && mvShapeMVP.iMVY != NOT_MV);
// mvShapeMVP = CMotionVector ((mvShapeMVP.iMVX * 2 + mvShapeMVP.iHalfX) / 2, //rounding
// (mvShapeMVP.iMVY * 2 + mvShapeMVP.iHalfY) / 2);
motionCompBY ((PixelC*) m_puciPredBAB->pixels (),
(PixelC*) pvopcRefQ->getPlane (BY_PLANE)->pixels (),
mvShapeMVP.iMVX + iX - 1,
mvShapeMVP.iMVY + iY - 1); //-1 due to 18x18 motion comp
}
// mvShapeMVP = findShapeMVP (pmv, pmvBY, pmbmd, iMBX, iMBY);
// assert (mvShapeMVP.iMVX != NOT_MV && mvShapeMVP.iMVY != NOT_MV);
// // mvShapeMVP = CMotionVector ((mvShapeMVP.iMVX * 2 + mvShapeMVP.iHalfX) / 2, //rounding
// // (mvShapeMVP.iMVY * 2 + mvShapeMVP.iHalfY) / 2);
// motionCompBY ((PixelC*) m_puciPredBAB->pixels (),
// (PixelC*) pvopcRefQ->getPlane (BY_PLANE)->pixels (),
// mvShapeMVP.iMVX + iX - 1,
// mvShapeMVP.iMVY + iY - 1); //-1 due to 18x18 motion comp
//~OBSSFIX_MODE3
if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
m_puciPredBAB->pixels (), m_rgiSubBlkIndx18x18, 18, pmbmd))
// zero mvd is ok
*pmvBY = mvShapeMVP;
else
{
// do block matching
CMotionVector mvShape;
//OBSSFIX_MODE3
if(m_volmd.volType == ENHN_LAYER && m_volmd.bSpatialScalability == 1 && m_volmd.iHierarchyType == 0 &&
m_volmd.iEnhnType != 0 && m_volmd.iuseRefShape == 1 && m_vopmd.vopPredType == PVOP){
mvShapeMVP.setToZero();
memset((void *)m_puciPredBAB->pixels(),255, MC_BAB_SIZE*MC_BAB_SIZE);
}else{
blkmatchForShape (pvopcRefQ,&mvShape, mvShapeMVP.trueMVHalfPel (), iX, iY);
assert (mvShape.iMVX != NOT_MV && mvShape.iMVY != NOT_MV);
*pmvBY = mvShape;
mvBYD = mvShape - mvShapeMVP;
motionCompBY ((PixelC*) m_puciPredBAB->pixels (),
(PixelC*) pvopcRefQ->getPlane (BY_PLANE)->pixels (),
mvShape.iMVX + iX - 1,
mvShape.iMVY + iY - 1); //-1 due to 18x18 motion comp
}
// blkmatchForShape (pvopcRefQ,&mvShape, mvShapeMVP.trueMVHalfPel (), iX, iY);
// assert (mvShape.iMVX != NOT_MV && mvShape.iMVY != NOT_MV);
// *pmvBY = mvShape;
// mvBYD = mvShape - mvShapeMVP;
// motionCompBY ((PixelC*) m_puciPredBAB->pixels (),
// (PixelC*) pvopcRefQ->getPlane (BY_PLANE)->pixels (),
// mvShape.iMVX + iX - 1,
// mvShape.iMVY + iY - 1); //-1 due to 18x18 motion comp
//~OBSSFIX_MODE3
}
// check status of motion compensated prediction BAB
PixelC *ppxlcPredBAB = (PixelC *)m_puciPredBAB->pixels()+MC_BAB_SIZE*MC_BAB_BORDER;
Int iXX,iYY,iOpaqueCount = 0;
for(iYY=MC_BAB_BORDER;iYY<MC_BAB_SIZE-MC_BAB_BORDER;iYY++,ppxlcPredBAB+=MC_BAB_SIZE)
for(iXX=MC_BAB_BORDER;iXX<MC_BAB_SIZE-MC_BAB_BORDER;iXX++)
if(ppxlcPredBAB[iXX] == opaqueValue)
iOpaqueCount++;
if(iOpaqueCount==0 || isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
m_puciPredBAB->pixels (), m_rgiSubBlkIndx18x18, 18, pmbmd))
{
// MC BAB is all transparent or not acceptable, so code.
round(ppxlcSrcFrm, pmbmd);
if(mvBYD.isZero())
pmbmd->m_shpmd = INTER_CAE_MVDZ;
else
pmbmd->m_shpmd = INTER_CAE_MVDNZ;
}
else if(pmbmd->m_shpmd==ALL_OPAQUE && !mvBYD.isZero())
;
else if(pmbmd->m_rgTranspStatus[0] == NONE && iOpaqueCount!=MB_SQUARE_SIZE)
pmbmd->m_shpmd=ALL_OPAQUE;
else if(mvBYD.isZero())
pmbmd->m_shpmd = MVDZ_NOUPDT;
else
pmbmd->m_shpmd = MVDNZ_NOUPDT;
}
switch(pmbmd->m_shpmd)
{
case ALL_OPAQUE:
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_ALL_OPAQUE");
#endif // __TRACE_AND_STATS_
pmvBY->iMVX = NOT_MV;
pmvBY->iMVY = NOT_MV;
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, OPAQUE);
return (codeShapeModeInter (ALL_OPAQUE, shpmdColocatedMB));
case ALL_TRANSP:
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ("MB_ALL_TRANSP");
#endif // __TRACE_AND_STATS_
pmvBY->iMVX = NOT_MV;
pmvBY->iMVY = NOT_MV;
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, TRANSPARENT);
return (codeShapeModeInter (ALL_TRANSP, shpmdColocatedMB));
case INTER_CAE_MVDZ:
case INTER_CAE_MVDNZ:
{
if (m_bNoShapeChg)
copyReconShapeToRef (ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
else
copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace ((PixelC *)m_puciPredBAB->pixels(), MC_BAB_SIZE, MC_BAB_SIZE, "MB_MC_PRED_BAB");
m_pbitstrmOut->trace (m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, TOTAL_BAB_SIZE, "MB_RECON_BAB (Ignore Borders)");
m_pbitstrmOut->trace (m_rgpxlcCaeSymbol, m_iWidthCurrBAB , m_iWidthCurrBAB , "MB_ENCODED_BAB");
#endif // __TRACE_AND_STATS_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -