⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbenc.cpp

📁 此源码是在VC平台下,实现MPEG4编解码的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*************************************************************************

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 Center

and 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.cpp

Abstract:

	MacroBlock encoder

Revision 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.net

NOTE:
	
	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_FILE
static 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 + -