📄 blkenc.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 Fujitsu Laboratories Ltd. (contact: Eishi Morimatsu)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.cppAbstract: functions for block-level encoding.Revision History: Sep.13 1999 : RRV added by Eishi Morimatsu (Fujitsu Laboratories Ltd.) *************************************************************************/#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_FILEstatic char BASED_CODE THIS_FILE[] = __FILE__;#endif#define new DEBUG_NEW #endif // __MFC_// HHI Schueuer: sadctCScanSelectorForSADCT::CScanSelectorForSADCT(Int **rgiCurrMBCoeffWidth) : m_rgiCurrMBCoeffWidth(rgiCurrMBCoeffWidth){ m_adaptedScan = new Int[BLOCK_SQUARE_SIZE];}CScanSelectorForSADCT::~CScanSelectorForSADCT(){ delete [] m_adaptedScan;} Int *CScanSelectorForSADCT::select(Int *scan, Bool bIsBoundary, Int iBlk){ if (bIsBoundary) { // the incoming scan is the zigzag scan for an 8x8 block which must be modified for // sadct coded boundary blocks. const Int *pCoeffWidth = m_rgiCurrMBCoeffWidth[iBlk]; int n, iy, ix; int coeff_count = 0; int coeff_count_save = 0; Int scan_save[BLOCK_SQUARE_SIZE]; for (n=0; n<BLOCK_SQUARE_SIZE; n++) { iy = scan[n]/BLOCK_SIZE; ix = scan[n] % BLOCK_SIZE; if (pCoeffWidth[iy] > ix) m_adaptedScan[coeff_count++] = scan[n]; else scan_save[coeff_count_save++] = scan[n]; } coeff_count_save = 0; for (n=coeff_count; n<BLOCK_SQUARE_SIZE; n++) m_adaptedScan[coeff_count++] = scan_save[coeff_count_save++]; return(m_adaptedScan); } else return(scan); }// end// 09/19/99 HHI SchueuerInt *CScanSelectorForSADCT::select_DP(Int *scan, Bool bIsBoundary, Int iBlk, Int** rgiCurrMBCoeffWidth){ if (bIsBoundary) { // the incoming scan is the zigzag scan for an 8x8 block which must be modified for // sadct coded boundary blocks. const Int *pCoeffWidth = rgiCurrMBCoeffWidth[iBlk]; int n, iy, ix; int coeff_count = 0; int coeff_count_save = 0; Int scan_save[BLOCK_SQUARE_SIZE]; for (n=0; n<BLOCK_SQUARE_SIZE; n++) { iy = scan[n]/BLOCK_SIZE; ix = scan[n] % BLOCK_SIZE; if (pCoeffWidth[iy] > ix) m_adaptedScan[coeff_count++] = scan[n]; else scan_save[coeff_count_save++] = scan[n]; } coeff_count_save = 0; for (n=coeff_count; n<BLOCK_SQUARE_SIZE; n++) m_adaptedScan[coeff_count++] = scan_save[coeff_count_save++]; return(m_adaptedScan); } else return(scan); }// end 09/19/99// HHI Schueuer: added const PixelC *rgpxlcBlkShape, Int iBlkShapeWidth for sadct 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, const PixelC *rgpxlcBlkShape, Int iBlkShapeWidth, Int iAuxComp ) {// m_pentrencSet->m_pentrencDCT->bitstream()->trace (ppxlcCurrQBlock, "BLK_TEXTURE"); // HHI Schueuer: added for sadct Int *lx = new Int [iBlkShapeWidth]; m_pfdct->apply (ppxlcBlkSrc, iWidthSrc, m_rgiDCTcoef, BLOCK_SIZE, rgpxlcBlkShape, iBlkShapeWidth, lx); // RRV insertion if(m_vopmd.RRVmode.iOnOff == 1) { cutoffDCTcoef(); } // ~RRV Bool bClip = TRUE; if(iBlk>=A_BLOCK1 && pmbmdCurr->m_pCODAlpha[iAuxComp] == ALPHA_ALL255) bClip = FALSE; // for correct dc value for intra dc prediction quantizeIntraDCcoef (rgiCoefQ, (Float) iDcScaler, bClip); inverseQuantizeIntraDc (rgiCoefQ, iDcScaler); //get the quantized block if (m_volmd.fQuantizer == Q_H263) { quantizeIntraDCTcoefH263 (rgiCoefQ, 1, iQP); // HHI Schueuer: sadct if (rgpxlcBlkShape && !m_volmd.bSadctDisable) { // assert(pmbmd->m_rgTranspStatus [iBlk] == PARTIAL); // brute force method to clean out mispredictions outside the active region // Int *lx = m_rgiCurrMBCoeffWidth[iBlk]; Int iy, ix; for (iy = 0; iy < BLOCK_SIZE; iy++) { for (ix=lx[iy]; ix<BLOCK_SIZE; ix++) rgiCoefQ[ix + iy * BLOCK_SIZE] = 0; } } //end HHI inverseQuantizeDCTcoefH263 (rgiCoefQ, 1, iQP); //get the quantized block } else { quantizeIntraDCTcoefMPEG (rgiCoefQ, 1, iQP, (iBlk > V_BLOCK)); // HHI Schueuer: sadct if (rgpxlcBlkShape && !m_volmd.bSadctDisable) { // assert(pmbmd->m_rgTranspStatus [iBlk] == PARTIAL); // brute force method to clean out mispredictions outside the active region Int *lx = m_rgiCurrMBCoeffWidth[iBlk]; Int iy, ix; for (iy = 0; iy < BLOCK_SIZE; iy++) { for (ix=lx[iy]; ix<BLOCK_SIZE; ix++) rgiCoefQ[ix + iy * BLOCK_SIZE] = 0; } } //end inverseQuantizeIntraDCTcoefMPEG (rgiCoefQ, 1, iQP, (iBlk > V_BLOCK), 0); //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, iBlk, &(m_rgblkmCurrMB [iBlk - 1]), pmbmLeft, pmbmTop, pmbmLeftTop, pmbmCurr, pmbmdLeft, pmbmdTop, pmbmdLeftTop, pmbmdCurr, m_rgiQPpred [iBlk - 1], iQP); if(iBlk < A_BLOCK1 || pmbmdCurr->m_pCODAlpha[iAuxComp] == ALPHA_CODED) // m_pidct->apply (m_rgiDCTcoef, BLOCK_SIZE, ppxlcCurrQBlock, iWidthCurrQ); // HHI Schueuer: rgpxlcBlkShape, iBlkShapeWidth added for sadct { //if(iBlk==A_BLOCK1 || iBlk==A_BLOCK2) //{ // printf("[%d,%d]",iQP,rgiCoefQ[0]); //} m_pidct->apply (m_rgiDCTcoef, BLOCK_SIZE, ppxlcCurrQBlock, iWidthCurrQ, rgpxlcBlkShape, iBlkShapeWidth); } // end HHI // fix memory leak (10000 more to go ;-) - swinder delete lx; return iSumErr;}Void CVideoObjectEncoder::quantizeIntraDCcoef (Int* rgiCoefQ, Float fltDcScaler, Bool bClip){ 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; if(bClip) { Int iMaxDC = (1<<m_volmd.nBits) - 2; // NBIT 1..254 rgiCoefQ [0] = (Int) max (1, min (iMaxDC, fltDCquantized)); } else rgiCoefQ [0] = (Int) 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[0]; 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[0]; 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, Int blkn, const BlockMemory * pblkmRet, 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; *pblkmRet = 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) { *pblkmRet = 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. } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -