📄 mbenc.cpp
字号:
/*************************************************************************This software module was originally developed by Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation Simon Winder (swinder@microsoft.com), Microsoft Corporation (date: June, 1997)and edited by Wei Wu (weiwu@stallion.risc.rockwell.com) Rockwell Science Centerand also edited by Yoshihiro Kikuchi (TOSHIBA CORPORATION) Takeshi Nagai (TOSHIBA CORPORATION) Toshiaki Watanabe (TOSHIBA CORPORATION) Noboru Yamaguchi (TOSHIBA CORPORATION)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: MBenc.cppAbstract: MacroBlock encoderRevision History: This software module was edited by Hiroyuki Katata (katata@imgsl.mkhar.sharp.co.jp), Sharp Corporation Norio Ito (norio@imgsl.mkhar.sharp.co.jp), Sharp Corporation Shuichi Watanabe (watanabe@imgsl.mkhar.sharp.co.jp), Sharp Corporation (date: October, 1997) for object based temporal scalability. Dec 20, 1997: Interlaced tools added by NextLevel Systems X.Chen, B. Eifrig May. 9 1998: add boundary by Hyundai Electronics Cheol-Soo Park (cspark@super5.hyundai.co.kr) May 9, 1999: tm5 rate control by DemoGraFX, duhoff@mediaone.netNOTE: m_pvopfCurrQ holds the original data until it is texture quantized*************************************************************************/#include <stdlib.h>#include <math.h>#include <iostream.h>#include "typeapi.h"#include "codehead.h"#include "mode.hpp"#include "global.hpp"#include "entropy/bitstrm.hpp"#include "entropy/entropy.hpp"#include "entropy/huffman.hpp"#include "vopses.hpp"#include "vopseenc.hpp"#ifdef __MFC_#ifdef _DEBUG#undef THIS_FILEstatic char BASED_CODE THIS_FILE[] = __FILE__;#endif#define new DEBUG_NEW #endif // __MFC_/*Void CVideoObjectEncoder::encodePVOPMBWithShape ( PixelC* ppxlcRefMBY, PixelC* ppxlcRefMBU, PixelC* ppxlcRefMBV, PixelC* ppxlcRefMBA, PixelC* ppxlcRefBY, CMBMode* pmbmd, const CMotionVector* pmv, CMotionVector* pmvBY, ShapeMode shpmdColocatedMB, Int imbX, Int imbY, CoordI x, CoordI y, Int& iQPPrev){ encodePVOPMBJustShape(ppxlcRefBY,pmbmd,shpmdColocatedMB,pmv,pmvBY,x,y,imbX,imbY); dumpCachedShapeBits(); encodePVOPMBTextureWithShape(ppxlcRefMBY,ppxlcRefMBU,ppxlcRefMBV,ppxlcRefMBA,pmbmd, pmv,imbX,imbY,x,y,iQPPrev);}*/Void CVideoObjectEncoder::encodePVOPMBJustShape( PixelC* ppxlcRefBY, CMBMode* pmbmd, ShapeMode shpmdColocatedMB, const CMotionVector* pmv, CMotionVector* pmvBY, CoordI x, CoordI y, Int imbX, Int imbY){ m_statsMB.nBitsShape += codeInterShape ( ppxlcRefBY, m_pvopcRefQ0, pmbmd, shpmdColocatedMB, pmv, pmvBY, x, y, imbX, imbY ); // change pmbmd to inter if all transparent decideTransparencyStatus (pmbmd, m_ppxlcCurrMBBY);}Void CVideoObjectEncoder::dumpCachedShapeBits(){#ifdef __TRACE_AND_STATS_ m_pbitstrmOut->trace("INSERTING PRE-ENCODED MB SHAPE STREAM HERE\n"); m_pbitstrmOut->trace(m_pbitstrmOut->getCounter(),"Location Before");#endif // __TRACE_AND_STATS_ m_pbitstrmOut->putBitStream(*m_pbitstrmShapeMBOut);#ifdef __TRACE_AND_STATS_ m_pbitstrmOut->trace(m_pbitstrmOut->getCounter(),"Location After");#endif // __TRACE_AND_STATS_ m_pbitstrmShapeMBOut->flush(); m_pbitstrmShapeMBOut->resetAll();}Void CVideoObjectEncoder::encodePVOPMBTextureWithShape( PixelC* ppxlcRefMBY, PixelC* ppxlcRefMBU, PixelC* ppxlcRefMBV, PixelC* ppxlcRefMBA, CMBMode* pmbmd, const CMotionVector* pmv, Int imbX, Int imbY, CoordI x, CoordI y, Int& iQPPrev, Int &iQPPrevAlpha, Bool &bUseNewQPForVlcThr){ // update quantiser pmbmd->m_stepSize = iQPPrev + pmbmd->m_intStepDelta; if(bUseNewQPForVlcThr) pmbmd->m_stepSizeDelayed = pmbmd->m_stepSize; else pmbmd->m_stepSizeDelayed = iQPPrev; iQPPrev = pmbmd->m_stepSize; if (pmbmd -> m_dctMd == INTRA || pmbmd -> m_dctMd == INTRAQ) { if(pmbmd -> m_rgTranspStatus [0] == PARTIAL) LPEPadding (pmbmd); if (m_volmd.fAUsage == EIGHT_BIT) { // update alpha quant if(!m_volmd.bNoGrayQuantUpdate) { iQPPrevAlpha = (iQPPrev * m_vopmd.intStepPAlpha) / m_vopmd.intStep; if(iQPPrevAlpha<1) iQPPrevAlpha=1; } pmbmd->m_stepSizeAlpha = iQPPrevAlpha; } assert (pmbmd -> m_rgTranspStatus [0] != ALL); /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_rgTranspStatus [0] == PARTIAL) boundaryMacroBlockMerge (pmbmd); // End of Hyundai(1998-5-9)*/ quantizeTextureIntraMB (imbX, imbY, pmbmd, ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV, ppxlcRefMBA); codeMBTextureHeadOfPVOP (pmbmd); sendDCTCoefOfIntraMBTexture (pmbmd); if (m_volmd.fAUsage == EIGHT_BIT) { codeMBAlphaHeadOfPVOP (pmbmd); sendDCTCoefOfIntraMBAlpha (pmbmd); } /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_bMerged[0]) mergedMacroBlockSplit (pmbmd, ppxlcRefMBY, ppxlcRefMBA); // End of Hyundai(1998-5-9)*/ bUseNewQPForVlcThr = FALSE; } else { // INTER or skipped if (m_volmd.fAUsage == EIGHT_BIT) { // update alpha quant if(!m_volmd.bNoGrayQuantUpdate) iQPPrevAlpha = (iQPPrev * m_vopmd.intStepPAlpha) / m_vopmd.intStep; pmbmd->m_stepSizeAlpha = iQPPrevAlpha; } if (pmbmd -> m_rgTranspStatus [0] == PARTIAL) { CoordI xRefUV, yRefUV;// INTERLACE // new changes if(pmbmd->m_bFieldMV) { CoordI xRefUV1, yRefUV1; mvLookupUV (pmbmd, pmv, xRefUV, yRefUV, xRefUV1, yRefUV1); motionCompFieldUV(m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y, xRefUV, yRefUV, pmbmd->m_bForwardTop); motionCompFieldUV(m_ppxlcPredMBU + BLOCK_SIZE, m_ppxlcPredMBV + BLOCK_SIZE, m_pvopcRefQ0, x, y, xRefUV1, yRefUV1, pmbmd->m_bForwardBottom); } else {// ~INTERLACE mvLookupUVWithShape (pmbmd, pmv, xRefUV, yRefUV); motionCompUV (m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y, xRefUV, yRefUV, m_vopmd.iRoundingControl,&m_rctRefVOPY0); } motionCompMBYEnc (pmv, pmbmd, imbX, imbY, x, y, &m_rctRefVOPY0); computeTextureErrorWithShape (); } else { // not partial CoordI xRefUV, yRefUV, xRefUV1, yRefUV1; mvLookupUV (pmbmd, pmv, xRefUV, yRefUV, xRefUV1, yRefUV1);// INTERLACE // new changes if(pmbmd->m_bFieldMV) { motionCompFieldUV(m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y, xRefUV, yRefUV, pmbmd->m_bForwardTop); motionCompFieldUV(m_ppxlcPredMBU + BLOCK_SIZE, m_ppxlcPredMBV + BLOCK_SIZE, m_pvopcRefQ0, x, y, xRefUV1, yRefUV1, pmbmd->m_bForwardBottom); } else {// ~INTERLACE motionCompUV (m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y, xRefUV, yRefUV, m_vopmd.iRoundingControl, &m_rctRefVOPY0); } motionCompMBYEnc (pmv, pmbmd, imbX, imbY, x, y, &m_rctRefVOPY0); computeTextureError (); } Bool bSkip = pmbmd->m_bhas4MVForward ? (pmv [1].isZero () && pmv [2].isZero () && pmv [3].isZero () && pmv [4].isZero ()) : (!pmbmd->m_bFieldMV && pmv->isZero()) ; /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_rgTranspStatus [0] == PARTIAL) boundaryMacroBlockMerge (pmbmd); // End of Hyundai(1998-5-9)*/ if(!m_volmd.bAllowSkippedPMBs) bSkip = FALSE; quantizeTextureInterMB (pmbmd, pmv, ppxlcRefMBA, bSkip); // decide COD here codeMBTextureHeadOfPVOP (pmbmd); if (!pmbmd -> m_bSkip) { /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_bMerged[0]) swapTransparentModes (pmbmd, BBS); // End of Hyundai(1998-5-9)*/ m_statsMB.nBitsMV += encodeMVWithShape (pmv, pmbmd, imbX, imbY); /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_bMerged[0]) swapTransparentModes (pmbmd, BBM); // End of Hyundai(1998-5-9)*/ sendDCTCoefOfInterMBTexture (pmbmd); // addErrorAndPredToCurrQ (ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); // delete by Hyundai, ok swinder } else assignPredToCurrQ (ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); if (m_volmd.fAUsage == EIGHT_BIT) { codeMBAlphaHeadOfPVOP (pmbmd); if (pmbmd -> m_CODAlpha == ALPHA_CODED) { sendDCTCoefOfInterMBAlpha (pmbmd); // addAlphaErrorAndPredToCurrQ (ppxlcRefMBA); // delete by Hyundai. ok swinder } else if(pmbmd -> m_CODAlpha == ALPHA_SKIPPED) assignAlphaPredToCurrQ (ppxlcRefMBA); } /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_bMerged[0]) mergedMacroBlockSplit (pmbmd); // End of Hyundai(1998-5-9)*/ if (!pmbmd -> m_bSkip) { bUseNewQPForVlcThr = FALSE; addErrorAndPredToCurrQ (ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); } if (m_volmd.fAUsage == EIGHT_BIT && pmbmd -> m_CODAlpha == ALPHA_CODED) addAlphaErrorAndPredToCurrQ (ppxlcRefMBA); }}Void CVideoObjectEncoder::encodePVOPMB ( PixelC* ppxlcRefMBY, PixelC* ppxlcRefMBU, PixelC* ppxlcRefMBV, CMBMode* pmbmd, const CMotionVector* pmv, Int iMBX, Int iMBY, CoordI x, CoordI y){ // For Sprite update macroblock there is no motion compensation if (m_uiSprite == 1 && m_vopmd.SpriteXmitMode != STOP) { if ( m_bSptMB_NOT_HOLE ) { m_iNumSptMB++ ; CopyCurrQToPred(ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); computeTextureError (); Bool bSkip = pmbmd->m_bhas4MVForward ? (pmv [1].isZero () && pmv [2].isZero () && pmv [3].isZero () && pmv [4].isZero ()) : pmv->isZero (); quantizeTextureInterMB (pmbmd, pmv, NULL, bSkip); // decide COD here codeMBTextureHeadOfPVOP (pmbmd); if (!pmbmd -> m_bSkip) { sendDCTCoefOfInterMBTexture (pmbmd); addErrorAndPredToCurrQ (ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); } } else { pmbmd -> m_bSkip = TRUE; codeMBTextureHeadOfPVOP (pmbmd); } return; } if (pmbmd->m_dctMd == INTRA || pmbmd->m_dctMd == INTRAQ) { pmbmd->m_bSkip = FALSE; //in case use by direct mode in the future quantizeTextureIntraMB (iMBX, iMBY, pmbmd, ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV, NULL); codeMBTextureHeadOfPVOP (pmbmd); sendDCTCoefOfIntraMBTexture (pmbmd); } else { CoordI xRefUV, yRefUV, xRefUV1, yRefUV1; mvLookupUV (pmbmd, pmv, xRefUV, yRefUV, xRefUV1, yRefUV1);// INTERLACE // pmbmd->m_rgTranspStatus[0] = NONE; // This a rectangular VOP if(pmbmd->m_bFieldMV) { motionCompFieldUV(m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y, xRefUV, yRefUV, pmbmd->m_bForwardTop); motionCompFieldUV(m_ppxlcPredMBU + BLOCK_SIZE, m_ppxlcPredMBV + BLOCK_SIZE, m_pvopcRefQ0, x, y, xRefUV1, yRefUV1, pmbmd->m_bForwardBottom); } else // ~INTERLACE motionCompUV (m_ppxlcPredMBU, m_ppxlcPredMBV, m_pvopcRefQ0, x, y, xRefUV, yRefUV, m_vopmd.iRoundingControl,&m_rctRefVOPY0); motionCompMBYEnc (pmv, pmbmd, iMBX, iMBY, x, y, &m_rctRefVOPY0); computeTextureError (); Bool bSkip = pmbmd->m_bhas4MVForward ? (pmv [1].isZero () && pmv [2].isZero () && pmv [3].isZero () && pmv [4].isZero ()) : (!pmbmd->m_bFieldMV && pmv->isZero()); if(!m_volmd.bAllowSkippedPMBs) bSkip = FALSE; quantizeTextureInterMB (pmbmd, pmv, NULL, bSkip); // decide COD here codeMBTextureHeadOfPVOP (pmbmd); if (!pmbmd -> m_bSkip) { if(!(m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode == 3)) m_statsMB.nBitsMV += encodeMVVP (pmv, pmbmd, iMBX, iMBY); sendDCTCoefOfInterMBTexture (pmbmd); addErrorAndPredToCurrQ (ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); } else { assignPredToCurrQ (ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV); } }}Void CVideoObjectEncoder::encodeBVOPMB ( PixelC* ppxlcCurrQMBY, PixelC* ppxlcCurrQMBU, PixelC* ppxlcCurrQMBV, CMBMode* pmbmd, const CMotionVector* pmv, const CMotionVector* pmvBackward, const CMBMode* pmbmdRef, const CMotionVector* pmvRef, Int iMBX, Int iMBY, CoordI x, CoordI y){ motionCompAndDiff_BVOP_MB (pmv, pmvBackward, pmbmd, x, y, &m_rctRefVOPY0, &m_rctRefVOPY1); Bool bSkip; if (m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode == 0 && pmbmd->m_mbType == FORWARD) bSkip = (pmv->m_vctTrueHalfPel.x ==0 && pmv->m_vctTrueHalfPel.y == 0); else if (pmbmd->m_mbType == DIRECT) bSkip = (pmbmd->m_vctDirectDeltaMV.x ==0 && pmbmd->m_vctDirectDeltaMV.y == 0); else bSkip = FALSE; quantizeTextureInterMB (pmbmd, pmv, NULL, bSkip); // decide COD here; skip not allowed in non-direct mode codeMBTextureHeadOfBVOP (pmbmd); if (!pmbmd->m_bSkip) { m_statsMB.nBitsMV += encodeMVofBVOP (pmv, pmvBackward, pmbmd, iMBX, iMBY, pmvRef, pmbmdRef); sendDCTCoefOfInterMBTexture (pmbmd); addErrorAndPredToCurrQ (ppxlcCurrQMBY, ppxlcCurrQMBU, ppxlcCurrQMBV); } else assignPredToCurrQ (ppxlcCurrQMBY, ppxlcCurrQMBU, ppxlcCurrQMBV);}Void CVideoObjectEncoder::encodeBVOPMB_WithShape ( PixelC* ppxlcCurrQMBY, PixelC* ppxlcCurrQMBU, PixelC* ppxlcCurrQMBV, PixelC* ppxlcCurrQMBA, PixelC* ppxlcCurrQBY, CMBMode* pmbmd, const CMotionVector* pmv, const CMotionVector* pmvBackward, CMotionVector* pmvBY, ShapeMode shpmdColocatedMB, const CMBMode* pmbmdRef, const CMotionVector* pmvRef, Int iMBX, Int iMBY, CoordI x, CoordI y, Int &iQPPrev, Int &iQPPrevAlpha){ pmbmd->m_stepSize = iQPPrev; if(!m_volmd.bNoGrayQuantUpdate) { iQPPrevAlpha = (iQPPrev * m_vopmd.intStepBAlpha) / m_vopmd.intStepB; if(iQPPrevAlpha<1) iQPPrevAlpha=1; } pmbmd->m_stepSizeAlpha = iQPPrevAlpha; m_statsMB.nBitsShape += codeInterShape ( ppxlcCurrQBY, m_vopmd.fShapeBPredDir==B_FORWARD ? m_pvopcRefQ0 : m_pvopcRefQ1, pmbmd, shpmdColocatedMB, NULL, pmvBY, x, y, iMBX, iMBY ); downSampleBY (m_ppxlcCurrMBBY, m_ppxlcCurrMBBUV); decideTransparencyStatus (pmbmd, m_ppxlcCurrMBBY); // change pmbmd to inter if all transparent /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace) initMergedMode (pmbmd); // End of Hyundai(1998-5-9)*/ if (m_volmd.bShapeOnly == FALSE && pmbmd->m_rgTranspStatus [0] != ALL) { if (pmbmd->m_rgTranspStatus [0] == PARTIAL) motionCompAndDiff_BVOP_MB_WithShape (pmv, pmvBackward, pmbmd, x, y, &m_rctRefVOPY0, &m_rctRefVOPY1); else motionCompAndDiff_BVOP_MB (pmv, pmvBackward, pmbmd, x, y, &m_rctRefVOPY0, &m_rctRefVOPY1); Bool bSkip = FALSE; if (pmbmd->m_mbType == DIRECT) { if(pmvRef == NULL) //just to be safe pmbmd->m_vctDirectDeltaMV = pmv->m_vctTrueHalfPel; bSkip = (pmbmd->m_vctDirectDeltaMV.x == 0) && (pmbmd->m_vctDirectDeltaMV.y == 0); } if(m_volmd.fAUsage == EIGHT_BIT) motionCompAndDiffAlpha_BVOP_MB ( pmv, pmvBackward, pmbmd, x, y, &m_rctRefVOPY0, &m_rctRefVOPY1 ); /*BBM// Added for Boundary by Hyundai(1998-5-9) if (m_vopmd.bInterlace && pmbmd -> m_rgTranspStatus [0] == PARTIAL) boundaryMacroBlockMerge (pmbmd); // End of Hyundai(1998-5-9)*/ quantizeTextureInterMB (pmbmd, pmv, ppxlcCurrQMBA, bSkip); // decide COD here; skip not allowed in non-direct mode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -