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

📄 blkenc.cpp

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

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 Center

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:
	
	blkenc.cpp

Abstract:

	functions for block-level encoding.

Revision History:

*************************************************************************/

#include <stdlib.h>
#include <math.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 "dct.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_

Int CVideoObjectEncoder::quantizeIntraBlockTexture (PixelC* ppxlcBlkSrc, 
													 Int iWidthSrc,													 
													 PixelC* ppxlcCurrQBlock, 
													 Int iWidthCurrQ,
													 Int* rgiCoefQ, 
													 Int iQP,
													 Int iDcScaler,
													 Int iBlk, 
													 MacroBlockMemory* pmbmLeft, 
													 MacroBlockMemory* pmbmTop, 
													 MacroBlockMemory* pmbmLeftTop,
													 MacroBlockMemory* pmbmCurr,
													 CMBMode* pmbmdLeft,
													 CMBMode* pmbmdTop,
													 CMBMode* pmbmdLeftTop,
													 CMBMode* pmbmdCurr)	
{
//	m_pentrencSet->m_pentrencDCT->bitstream()->trace (ppxlcCurrQBlock, "BLK_TEXTURE");
	m_pfdct->apply  (ppxlcBlkSrc, iWidthSrc, m_rgiDCTcoef, BLOCK_SIZE);
	quantizeIntraDCcoef (rgiCoefQ, (Float) iDcScaler);
	inverseQuantizeIntraDc (rgiCoefQ, iDcScaler);			//get the quantized block
	if (m_volmd.fQuantizer == Q_H263)	{
		quantizeIntraDCTcoefH263 (rgiCoefQ, 1, iQP);	
		inverseQuantizeDCTcoefH263 (rgiCoefQ, 1, iQP);		//get the quantized block
	}
	else	{
		quantizeIntraDCTcoefMPEG (rgiCoefQ, 1, iQP, (iBlk > V_BLOCK));	
		inverseQuantizeIntraDCTcoefMPEG (rgiCoefQ, 1, iQP, (iBlk > V_BLOCK));											//get the quantized block
	}

	Int i, j;
//	pmbmCurr->rgblkm [iBlk - 1] [0] = rgiCoefQ [0];		//save Qcoef in memory
	pmbmCurr->rgblkm [iBlk - 1] [0] = m_rgiDCTcoef [0];		//save reconstructed DC but quantized AC in memory
	for (i = 1, j = 8; i < BLOCK_SIZE; i++, j += BLOCK_SIZE)	{
		pmbmCurr->rgblkm [iBlk - 1] [i] = rgiCoefQ [i];
		pmbmCurr->rgblkm [iBlk - 1] [i + BLOCK_SIZE - 1] = rgiCoefQ [j];
	}

	Int iSumErr = 0;
	m_rgiQPpred [iBlk - 1] = iQP; //default to current in case no predictor
	iSumErr += decideIntraPredDir (	rgiCoefQ,
									(BlockNum) iBlk,
									m_rgblkmCurrMB [iBlk - 1],
									pmbmLeft, 
  									pmbmTop, 
									pmbmLeftTop,									   
									pmbmCurr,
									pmbmdLeft,
									pmbmdTop,
									pmbmdLeftTop,
									pmbmdCurr,
									m_rgiQPpred [iBlk - 1],
									iQP);
	if(iBlk < A_BLOCK1 || pmbmdCurr->m_CODAlpha == ALPHA_CODED)
		m_pidct->apply (m_rgiDCTcoef, BLOCK_SIZE, ppxlcCurrQBlock, iWidthCurrQ);
	return iSumErr;
}

Void CVideoObjectEncoder::quantizeIntraDCcoef (Int* rgiCoefQ, Float fltDcScaler)
{
	if (m_volmd.nBits<=8) { // NBIT: may not valid when nBits>8
		assert (fltDcScaler > 0 && fltDcScaler < 128);
	}
#ifdef NO_APPENDIXF
	Float fltDCquantized = (Float) m_rgiDCTcoef [0] / 8.0F;
#else
	Float fltDCquantized = (Float) m_rgiDCTcoef [0] / fltDcScaler;
#endif
	assert (fltDCquantized >= 0);
	fltDCquantized = fltDCquantized + 0.5F;
	Int iMaxDC = (1<<m_volmd.nBits) - 2; // NBIT 1..254
	rgiCoefQ [0] = (Int) max (1, min (iMaxDC, fltDCquantized));
}

Void CVideoObjectEncoder::quantizeIntraDCTcoefH263 (Int* rgiCoefQ, Int iStart, Int iQP)
{
	Int iLevelBits = 12; // 12 bit FLC (= m_volmd.nBits?)
	Int iMaxAC = (1<<(iLevelBits - 1)) - 1; // NBIT 127
	for (Int i = iStart; i < BLOCK_SQUARE_SIZE; i++) {
		Int ilevel = sign(m_rgiDCTcoef [i]) * (abs (m_rgiDCTcoef [i]) / (2 * iQP));
		rgiCoefQ [i] =  min(iMaxAC, max(-iMaxAC, ilevel));
	}
}

Void CVideoObjectEncoder::quantizeInterDCTcoefH263 (Int* rgiCoefQ, Int iStart, Int iQP)
{
	Int iLevelBits = 12; // 12 bit FLC (= m_volmd.nBits?)
	Int iMaxAC = (1<<(iLevelBits - 1)) - 1; // NBIT 127
	for (Int i = iStart; i < BLOCK_SQUARE_SIZE; i++) {
		Int ilevel = sign(m_rgiDCTcoef [i]) * ((abs (m_rgiDCTcoef [i]) - iQP / 2) / (2 * iQP));
		rgiCoefQ [i] =  min(iMaxAC, max(-iMaxAC, ilevel));
	}
}

Void CVideoObjectEncoder::quantizeIntraDCTcoefMPEG (Int* rgiCoefQ, Int iStart, Int iQP,
													Bool bUseAlphaMatrix)
{
	Float fltScaledCoef;
	Int i, iScaledQP, iScaledCoef;
	Int *piQuantizerMatrix;
	if(bUseAlphaMatrix)
		piQuantizerMatrix = m_volmd.rgiIntraQuantizerMatrixAlpha;
	else
		piQuantizerMatrix = m_volmd.rgiIntraQuantizerMatrix;
	Int iMaxVal = 1<<(m_volmd.nBits+3); // NBIT 2048
	Int iLevelBits = 12; // 12 bit FLC (= m_volmd.nBits?)
	Int iMaxAC = (1<<(iLevelBits - 1)) - 1; // NBIT 127

	for (i = iStart; i < BLOCK_SQUARE_SIZE; i++) {
		fltScaledCoef = 16.0F * m_rgiDCTcoef [i] / piQuantizerMatrix [i]; 
		iScaledCoef = (Int) rounded (fltScaledCoef);
		iScaledCoef = checkrange (iScaledCoef, -iMaxVal, iMaxVal - 1);
		iScaledQP = (Int) (3.0F * (Float) iQP / 4.0F + 0.5);
		assert (iScaledQP >= 0);
		iScaledCoef = (iScaledCoef + sign(iScaledCoef) * iScaledQP) / (2 * iQP);
		rgiCoefQ [i]  = min(iMaxAC, max(-iMaxAC, iScaledCoef ));
	}
}

Void CVideoObjectEncoder::quantizeInterDCTcoefMPEG (Int* rgiCoefQ, Int iStart, Int iQP,
													Bool bUseAlphaMatrix)
{
	Float fltScaledCoef;
	Int i, iScaledCoef;
	Int *piQuantizerMatrix;
	if(bUseAlphaMatrix)
		piQuantizerMatrix = m_volmd.rgiInterQuantizerMatrixAlpha;
	else
		piQuantizerMatrix = m_volmd.rgiInterQuantizerMatrix;
	Int iLevelBits = 12; // 12 bit FLC (= m_volmd.nBits?)
	Int iMaxAC = (1<<(iLevelBits - 1)) - 1; // NBIT 127

	for (i = iStart; i < BLOCK_SQUARE_SIZE; i++) {
		fltScaledCoef = 16.0F * m_rgiDCTcoef [i] / piQuantizerMatrix [i]; 
		iScaledCoef = (Int) rounded (fltScaledCoef);
		iScaledCoef  = iScaledCoef / (2 * iQP);
		rgiCoefQ [i] = min(iMaxAC, max(-iMaxAC, iScaledCoef ));
	}
}

Int CVideoObject::decideIntraPredDir (Int* rgiCoefQ,
									   BlockNum blkn,
									   const BlockMemory& blkmRet, 
									   const MacroBlockMemory* pmbmLeft, 
  									   const MacroBlockMemory* pmbmTop, 
									   const MacroBlockMemory* pmbmLeftTop,
									   const MacroBlockMemory* pmbmCurr,
									   const CMBMode* pmbmdLeft,
									   const CMBMode* pmbmdTop,
									   const CMBMode* pmbmdLeftTop,
									   CMBMode* pmbmdCurr,
									   Int&	iQPpred,
									   Int iQPcurr,
									   Bool bDecideDCOnly)
{
	UInt nBits = m_volmd.nBits;
	Int iDefVal = 1<<(nBits+2);// NBIT: start to calculate default value
	Int iRange = (1<<(nBits-1))-1; // 127 for 8-bit

	Int iQPpredTop, iQPpredLeftTop, iQPpredLeft;
	const BlockMemory blkmTop = findPredictorBlock (blkn, VERTICAL,
		pmbmLeft, pmbmTop, pmbmLeftTop, pmbmCurr,
		pmbmdLeft, pmbmdTop, pmbmdLeftTop, pmbmdCurr, iQPpredTop);
	const BlockMemory blkmLeftTop = findPredictorBlock (blkn, DIAGONAL,
		pmbmLeft, pmbmTop, pmbmLeftTop, pmbmCurr,
		pmbmdLeft, pmbmdTop, pmbmdLeftTop, pmbmdCurr, iQPpredLeftTop);
	const BlockMemory blkmLeft = findPredictorBlock (blkn, HORIZONTAL,
		pmbmLeft, pmbmTop, pmbmLeftTop, pmbmCurr,
		pmbmdLeft, pmbmdTop, pmbmdLeftTop, pmbmdCurr, iQPpredLeft);
	//wchen: changed to 1024 per CD (based on recon instead of Q value now)
/* NBIT: change 1024 to iDefVal
	Int iPredLeftTop = (blkmLeftTop == NULL) ? 1024 : blkmLeftTop [0];		
	Int iHorizontalGrad				= ((blkmTop  == NULL) ? 1024 : blkmTop  [0]) - iPredLeftTop;
	Int iVerticalGrad				= ((blkmLeft == NULL) ? 1024 : blkmLeft [0]) - iPredLeftTop;
*/
	Int iPredLeftTop = (blkmLeftTop == NULL) ? iDefVal : blkmLeftTop [0];		
	Int iHorizontalGrad				= ((blkmTop  == NULL) ? iDefVal : blkmTop  [0]) - iPredLeftTop;
	Int iVerticalGrad				= ((blkmLeft == NULL) ? iDefVal : blkmLeft [0]) - iPredLeftTop;

	blkmRet = NULL;
	UInt i, j;
	Int iSumErr = 0; //per vm4.0, p53
	if (abs(iVerticalGrad)  < abs (iHorizontalGrad))	{
		pmbmdCurr->m_preddir [blkn - 1] = VERTICAL;
		if (blkmTop != NULL)	{
			blkmRet = blkmTop;
			iQPpred = iQPpredTop;
			if (bDecideDCOnly != TRUE)	{
				for (i = 1; i < BLOCK_SIZE; i++)	{
					Int iDiff = rgiCoefQ [i] - divroundnearest(blkmTop [i] * iQPpred, iQPcurr);
					if (iDiff >= -iRange && iDiff <= iRange)	//hack to deal with vm deficiency: ac pred out of range; dc pred is not dealt with
						iSumErr += abs (rgiCoefQ [i]) - abs (iDiff);
					else
						return -100000;	//arbitrary  negative number to turn off ac pred.
				}
			}
		}
	}
	else	{
		pmbmdCurr->m_preddir [blkn - 1] = HORIZONTAL;
		if (blkmLeft != NULL)	{
			blkmRet = blkmLeft;
			iQPpred = iQPpredLeft;
			if (bDecideDCOnly != TRUE)	{
				for (i = 8, j = 8; i < BLOCK_SQUARE_SIZE; i += 8, j++)	{
					Int iDiff = rgiCoefQ [i] - divroundnearest(blkmLeft [j] * iQPpred, iQPcurr);
					if (iDiff >= -iRange && iDiff <= iRange)	//hack to deal with vm deficiency: ac pred out of range; dc pred is not dealt with
						iSumErr += abs (rgiCoefQ [i]) - abs (iDiff);
					else
						return -100000;	//arbitrary negative number to turn off ac pred.
				}
			}
		}
	}
	return iSumErr;
}


Void CVideoObjectEncoder::intraPred (BlockNum blkn, const CMBMode* pmbmd, 
									 Int* rgiCoefQ, Int iQPcurr, Int iDcScaler, 
									 const BlockMemory blkmPred, Int iQPpred)
{
	Int iDefVal; // NBIT: start to calculate default value
	UInt nBits = m_volmd.nBits;
	Int iMaxDC = (1<<nBits) - 1;
	Int iLevelBits = 12; // 12 bit FLC (= m_volmd.nBits?)
	Int iMaxAC = (1<<(iLevelBits - 1)) - 1; // NBIT 127
	iDefVal = 1<<(nBits + 2);


	//do DC prediction
	if (blkmPred == NULL)
/* NBIT: change 1024 to iDefVal
		rgiCoefQ [0] -= (1024 + (iDcScaler >> 1)) / iDcScaler;
*/
		rgiCoefQ [0] -= divroundnearest(iDefVal, iDcScaler);
	else {
		rgiCoefQ [0] -= divroundnearest(blkmPred [0], iDcScaler);
/* NBIT: change 255 to iMaxVal
		assert (rgiCoefQ [0] >= -255 && rgiCoefQ [0] <= 255);
*/
		assert (rgiCoefQ [0] >= -iMaxDC && rgiCoefQ [0] <= iMaxDC);

		if (blkn < A_BLOCK1 && pmbmd->m_bACPrediction

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -