📄 vopmbenc.cpp
字号:
/*************************************************************************This software module was originally developed by Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation Bruce Lin (blin@microsoft.com), Microsoft Corporation Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation Simon Winder (swinder@microsoft.com), Microsoft Corporation (date: March, 1996)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: vopmbEnc.cppAbstract: Encode MB's for each VOP (I-, P-, and B-VOP's)Revision History: Dec. 11, 1997: Interlaced tools added by NextLevel Systems (GI) B. Eifrig, (beifrig@nlvl.com) X. Chen, (xchen@nlvl.com) May. 9 1998: add boundary by Hyundai Electronics Cheol-Soo Park (cspark@super5.hyundai.co.kr) May. 9 1998: add field based MC padding by Hyundai Electronics Cheol-Soo Park (cspark@super5.hyundai.co.kr) May 9, 1999: tm5 rate control by DemoGraFX, duhoff@mediaone.net*************************************************************************/#include <stdio.h>#include <math.h>#include <stdlib.h>#include <iostream.h>#include "typeapi.h"#include "codehead.h"#include "entropy/bitstrm.hpp"#include "entropy/entropy.hpp"#include "entropy/huffman.hpp"#include "mode.hpp"#include "global.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::encodeVOP () { if (m_uiRateControl>=RC_TM5) { m_tm5rc.tm5rc_init_pict(m_vopmd.vopPredType, m_pvopcOrig->pixelsBoundY (), m_iFrameWidthY, m_iNumMBX, m_iNumMBY); }// Added for Data Partitioning mode by Toshiba(1998-1-16) if( m_volmd.bDataPartitioning ) { if (m_volmd.fAUsage == RECTANGLE) { switch( m_vopmd.vopPredType ) { case PVOP: encodeNSForPVOP_DP (); break; case IVOP: encodeNSForIVOP_DP (); break; case BVOP: encodeNSForBVOP (); break; default: assert(FALSE); // B-VOP and Sprite-VOP are not supported in DP-mode } } else { switch( m_vopmd.vopPredType ) { case PVOP: encodeNSForPVOP_WithShape_DP (); break; case IVOP: encodeNSForIVOP_WithShape_DP (); break; case BVOP: encodeNSForBVOP_WithShape (); break; default: assert(FALSE); // B-VOP and Sprite-VOP are not supported in DP-mode } } } else// End Toshiba(1998-1-16) if (m_volmd.fAUsage == RECTANGLE) { if (m_vopmd.vopPredType == PVOP) encodeNSForPVOP (); else if (m_vopmd.vopPredType == IVOP) encodeNSForIVOP (); else encodeNSForBVOP (); } else { if (m_vopmd.vopPredType == PVOP) { if (m_uiSprite == 1 && m_sptMode != BASIC_SPRITE && m_vopmd.SpriteXmitMode != STOP) encodeNSForPVOP (); else encodeNSForPVOP_WithShape (); } else if (m_vopmd.vopPredType == IVOP) encodeNSForIVOP_WithShape (); else encodeNSForBVOP_WithShape (); } if (m_uiRateControl>=RC_TM5) { m_tm5rc.tm5rc_update_pict(m_vopmd.vopPredType, m_statsVOP.total()); }}//// size:// m_pvopcCurr: original size (QCIF or CIF), same memory through out the session// m_pvopfRef: expanded original size (QCIF or CIF expanded by 16), same memory through out the session// pmbmd and pmv: VOP. need to reallocate every time//// things don't need to recompute:// m_iWidthY, m_iWidthUV, m_iWidthRefY, m_iWidthRefUV// need to recompute:// m_uintNumMBX, m_uintNumMBY, m_uintNumMB//Void CVideoObjectEncoder::encodeNSForIVOP () { //in case the IVOP is used as an ref for direct mode memset (m_rgmv, 0, m_iNumMB * PVOP_MV_PER_REF_PER_MB * sizeof (CMotionVector)); CMBMode* pmbmd = m_rgmbmd; Int iQPPrev = m_vopmd.intStepI; //initialization PixelC* ppxlcRefY = (PixelC*) m_pvopcRefQ1->pixelsY () + m_iStartInRefToCurrRctY; PixelC* ppxlcRefU = (PixelC*) m_pvopcRefQ1->pixelsU () + m_iStartInRefToCurrRctUV; PixelC* ppxlcRefV = (PixelC*) m_pvopcRefQ1->pixelsV () + m_iStartInRefToCurrRctUV; PixelC* ppxlcOrigY = (PixelC*) m_pvopcOrig->pixelsBoundY (); PixelC* ppxlcOrigU = (PixelC*) m_pvopcOrig->pixelsBoundU (); PixelC* ppxlcOrigV = (PixelC*) m_pvopcOrig->pixelsBoundV (); // MB rate control //Int iIndexofQ = 0; //Int rgiQ [4] = {-1, -2, 1, 2}; if (m_uiRateControl>=RC_TM5) iQPPrev = m_tm5rc.tm5rc_start_mb(); // ----- Bool bRestartDelayedQP = TRUE; Int iMBX, iMBY, iMB = 0; Int iMaxQP = (1<<m_volmd.uiQuantPrecision)-1; // NBIT for (iMBY = 0; iMBY < m_iNumMBY; iMBY++) { PixelC* ppxlcRefMBY = ppxlcRefY; PixelC* ppxlcRefMBU = ppxlcRefU; PixelC* ppxlcRefMBV = ppxlcRefV; PixelC* ppxlcOrigMBY = ppxlcOrigY; PixelC* ppxlcOrigMBU = ppxlcOrigU; PixelC* ppxlcOrigMBV = ppxlcOrigV; // In a given Sprite object piece, identify whether current macroblock is not a hole and should be coded ? Bool bSptMB_NOT_HOLE= TRUE; if (m_uiSprite == 1 && m_sptMode != BASIC_SPRITE && m_vopmd.SpriteXmitMode != STOP) { bSptMB_NOT_HOLE = SptPieceMB_NOT_HOLE(0, iMBY, pmbmd); RestoreMBmCurrRow (iMBY, m_rgpmbmCurr); } for (iMBX = 0; iMBX < m_iNumMBX; iMBX++, iMB++) { // code current macroblock only if it is not a hole m_bSptMB_NOT_HOLE = bSptMB_NOT_HOLE; if (!m_bSptMB_NOT_HOLE) //low latency goto EOMB1;#ifdef __TRACE_AND_STATS_ m_statsMB.reset (); m_pbitstrmOut->trace (CSite (iMBX, iMBY), "MB_X_Y");#endif // __TRACE_AND_STATS_ pmbmd->m_intStepDelta = 0; // MB rate control if (m_uiRateControl>=RC_TM5) { pmbmd->m_intStepDelta = m_tm5rc.tm5rc_calc_mquant(iMB, m_statsVOP.total()) - iQPPrev; if (pmbmd->m_intStepDelta>2) pmbmd->m_intStepDelta = 2; else if (pmbmd->m_intStepDelta<-2) pmbmd->m_intStepDelta = -2; }#ifdef _MBQP_CHANGE_ iIndexofQ = (iIndexofQ + 1) % 4; pmbmd->m_intStepDelta = rgiQ [iIndexofQ];#endif //_MBQP_CHANGE_ pmbmd->m_bSkip = FALSE; //reset for direct mode pmbmd->m_stepSize = iQPPrev + pmbmd->m_intStepDelta;/* NBIT: change 31 to iMaxQP assert (pmbmd->m_stepSize <= 31 && pmbmd->m_stepSize > 0);*/ assert (pmbmd->m_stepSize <= iMaxQP && pmbmd->m_stepSize > 0); if ( m_volmd.bVPBitTh >= 0) { // modified by Sharp (98/4/13) Int iCounter = m_pbitstrmOut -> getCounter(); if( iCounter - m_iVPCounter > m_volmd.bVPBitTh ) { pmbmd->m_intStepDelta = 0; // reset DQ to use QP in VP header codeVideoPacketHeader (iMBX, iMBY, pmbmd->m_stepSize); // video packet header m_iVPCounter = iCounter; bRestartDelayedQP = TRUE; } }// End Toshiba(1998-1-16) if(bRestartDelayedQP) { pmbmd->m_stepSizeDelayed = pmbmd->m_stepSize; bRestartDelayedQP = FALSE; } else pmbmd->m_stepSizeDelayed = iQPPrev; iQPPrev = pmbmd->m_stepSize; if (pmbmd->m_intStepDelta == 0) pmbmd->m_dctMd = INTRA; else pmbmd->m_dctMd = INTRAQ; pmbmd->m_bFieldMV = 0; copyToCurrBuff (ppxlcOrigMBY, ppxlcOrigMBU, ppxlcOrigMBV, m_iFrameWidthY, m_iFrameWidthUV); quantizeTextureIntraMB (iMBX, iMBY, pmbmd, ppxlcRefMBY, ppxlcRefMBU, ppxlcRefMBV, NULL); codeMBTextureHeadOfIVOP (pmbmd); sendDCTCoefOfIntraMBTexture (pmbmd);EOMB1: pmbmd++;#ifdef __TRACE_AND_STATS_ m_statsVOP += m_statsMB;#endif // __TRACE_AND_STATS_ ppxlcRefMBY += MB_SIZE; ppxlcRefMBU += BLOCK_SIZE; ppxlcRefMBV += BLOCK_SIZE; ppxlcOrigMBY += MB_SIZE; ppxlcOrigMBU += BLOCK_SIZE; ppxlcOrigMBV += BLOCK_SIZE; if (m_uiSprite == 1 && m_sptMode != BASIC_SPRITE) { bSptMB_NOT_HOLE = SptPieceMB_NOT_HOLE(iMBX+1, iMBY, pmbmd); m_iNumSptMB++ ; } } MacroBlockMemory** ppmbmTemp = m_rgpmbmAbove; m_rgpmbmAbove = m_rgpmbmCurr; // dshu: begin of modification if (m_uiSprite == 1 && m_sptMode != BASIC_SPRITE) SaveMBmCurrRow (iMBY, m_rgpmbmCurr); // save current row pointed by *m_rgpmbmCurr // dshu: end of modification m_rgpmbmCurr = ppmbmTemp; ppxlcRefY += m_iFrameWidthYxMBSize; ppxlcRefU += m_iFrameWidthUVxBlkSize; ppxlcRefV += m_iFrameWidthUVxBlkSize; ppxlcOrigY += m_iFrameWidthYxMBSize; ppxlcOrigU += m_iFrameWidthUVxBlkSize; ppxlcOrigV += m_iFrameWidthUVxBlkSize; }}Void CVideoObjectEncoder::encodeNSForIVOP_WithShape (){ //in case the IVOP is used as an ref for direct mode memset (m_rgmv, 0, m_iNumMB * PVOP_MV_PER_REF_PER_MB * sizeof (CMotionVector)); memset (m_rgmvBY, 0, m_iNumMB * sizeof (CMotionVector)); Int iMBX, iMBY, iMB = 0; Int iMaxQP = (1<<m_volmd.uiQuantPrecision)-1; // NBIT CMBMode* pmbmd = m_rgmbmd; // Added for field based MC padding by Hyundai(1998-5-9) CMBMode* field_pmbmd = m_rgmbmd; // End of Hyundai(1998-5-9) Int iQPPrev = m_vopmd.intStepI; //initialization Int iQPPrevAlpha = m_vopmd.intStepIAlpha; if (m_uiRateControl>=RC_TM5) iQPPrev = m_tm5rc.tm5rc_start_mb(); PixelC* ppxlcRefY = (PixelC*) m_pvopcRefQ1->pixelsY () + m_iStartInRefToCurrRctY; PixelC* ppxlcRefU = (PixelC*) m_pvopcRefQ1->pixelsU () + m_iStartInRefToCurrRctUV; PixelC* ppxlcRefV = (PixelC*) m_pvopcRefQ1->pixelsV () + m_iStartInRefToCurrRctUV; PixelC* ppxlcRefBY = (PixelC*) m_pvopcRefQ1->pixelsBY () + m_iStartInRefToCurrRctY; PixelC* ppxlcRefBUV = (PixelC*) m_pvopcRefQ1->pixelsBUV () + m_iStartInRefToCurrRctUV; PixelC *ppxlcRefA = NULL, *ppxlcOrigA = NULL; PixelC* ppxlcOrigY = (PixelC*) m_pvopcOrig->pixelsBoundY (); PixelC* ppxlcOrigU = (PixelC*) m_pvopcOrig->pixelsBoundU (); PixelC* ppxlcOrigV = (PixelC*) m_pvopcOrig->pixelsBoundV (); PixelC* ppxlcOrigBY = (PixelC*) m_pvopcOrig->pixelsBoundBY (); if (m_volmd.fAUsage == EIGHT_BIT) { ppxlcRefA = (PixelC*) m_pvopcRefQ1->pixelsA () + m_iStartInRefToCurrRctY; ppxlcOrigA = (PixelC*) m_pvopcOrig->pixelsBoundA (); } Bool bRestartDelayedQP = TRUE; for (iMBY = 0; iMBY < m_iNumMBY; iMBY++) { PixelC* ppxlcRefMBY = ppxlcRefY; PixelC* ppxlcRefMBU = ppxlcRefU; PixelC* ppxlcRefMBV = ppxlcRefV; PixelC* ppxlcRefMBBY = ppxlcRefBY; PixelC* ppxlcRefMBBUV = ppxlcRefBUV; PixelC* ppxlcRefMBA = ppxlcRefA; PixelC* ppxlcOrigMBY = ppxlcOrigY; PixelC* ppxlcOrigMBU = ppxlcOrigU; PixelC* ppxlcOrigMBV = ppxlcOrigV; PixelC* ppxlcOrigMBBY = ppxlcOrigBY; PixelC* ppxlcOrigMBA = ppxlcOrigA; // In a given Sprite object piece, identify whether current macroblock is not a hole and should be coded ? Bool bSptMB_NOT_HOLE= TRUE; if (m_uiSprite == 1 && m_sptMode != BASIC_SPRITE && m_vopmd.SpriteXmitMode != STOP) { bSptMB_NOT_HOLE = SptPieceMB_NOT_HOLE(0, iMBY, pmbmd); RestoreMBmCurrRow (iMBY, m_rgpmbmCurr); } for (iMBX = 0; iMBX < m_iNumMBX; iMBX++, iMB++) { // code current macroblock only if it is not a hole m_bSptMB_NOT_HOLE = bSptMB_NOT_HOLE; if (!m_bSptMB_NOT_HOLE) goto EOMB2; // MB rate control if (m_uiRateControl>=RC_TM5) { pmbmd->m_intStepDelta = m_tm5rc.tm5rc_calc_mquant(iMB, m_statsVOP.total()) - iQPPrev; if (pmbmd->m_intStepDelta>2) pmbmd->m_intStepDelta = 2; else if (pmbmd->m_intStepDelta<-2) pmbmd->m_intStepDelta = -2; } // Added for error resilient mode by Toshiba(1997-11-14) pmbmd->m_stepSize = iQPPrev + pmbmd->m_intStepDelta; if ( m_volmd.bVPBitTh >= 0) { Int iCounter = m_pbitstrmOut -> getCounter(); if( iCounter - m_iVPCounter > m_volmd.bVPBitTh ) { codeVideoPacketHeader (iMBX, iMBY, pmbmd->m_stepSize); // video packet header m_iVPCounter = iCounter; bRestartDelayedQP = TRUE; } } // End Toshiba(1997-11-14) #ifdef __TRACE_AND_STATS_ m_statsMB.reset (); m_pbitstrmOut->trace (CSite (iMBX, iMBY), "MB_X_Y");#endif // __TRACE_AND_STATS_ pmbmd->m_bSkip = FALSE; //reset for direct mode pmbmd->m_bPadded=FALSE; copyToCurrBuffWithShape ( ppxlcOrigMBY, ppxlcOrigMBU, ppxlcOrigMBV, ppxlcOrigMBBY, ppxlcOrigMBA, m_iFrameWidthY, m_iFrameWidthUV ); downSampleBY (m_ppxlcCurrMBBY, m_ppxlcCurrMBBUV); // downsample original BY now for LPE padding (using original shape) decideTransparencyStatus (pmbmd, m_ppxlcCurrMBBY); if (pmbmd -> m_rgTranspStatus [0] == PARTIAL) { LPEPadding (pmbmd); m_statsMB.nBitsShape += codeIntraShape (ppxlcRefMBBY, pmbmd, iMBX, iMBY); downSampleBY (m_ppxlcCurrMBBY, m_ppxlcCurrMBBUV); decideTransparencyStatus (pmbmd, m_ppxlcCurrMBBY); // need to modify it a little (NONE block won't change) } else m_statsMB.nBitsShape += codeIntraShape (ppxlcRefMBBY, pmbmd, iMBX, iMBY); /*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) {// shape only mode pmbmd->m_stepSizeDelayed = iQPPrev; if (pmbmd -> m_rgTranspStatus [0] != ALL) { pmbmd->m_stepSize = iQPPrev + pmbmd->m_intStepDelta; assert (pmbmd->m_stepSize <= iMaxQP && pmbmd->m_stepSize > 0); if(bRestartDelayedQP) { pmbmd->m_stepSizeDelayed = pmbmd->m_stepSize; bRestartDelayedQP = FALSE; } iQPPrev = pmbmd->m_stepSize; if (pmbmd->m_intStepDelta == 0) pmbmd->m_dctMd = INTRA; else pmbmd->m_dctMd = INTRAQ; if (m_volmd.fAUsage == EIGHT_BIT) { // update alpha quant if(!m_volmd.bNoGrayQuantUpdate) { iQPPrevAlpha = (iQPPrev * m_vopmd.intStepIAlpha) / m_vopmd.intStepI; if(iQPPrevAlpha<1) iQPPrevAlpha=1; } pmbmd->m_stepSizeAlpha = iQPPrevAlpha; } /*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); codeMBTextureHeadOfIVOP (pmbmd); sendDCTCoefOfIntraMBTexture (pmbmd); if (m_volmd.fAUsage == EIGHT_BIT) { codeMBAlphaHeadOfIVOP (pmbmd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -