Void TComTrQuant::transformNxN( TComDataCU* pcCU,
Pel* pcResidual, //!< 殘差
UInt uiStride,
TCoeff* rpcCoeff, //!< 殘差經變換且量化後的係數
#if ADAPTIVE_QP_SELECTION
Int*& rpcArlCoeff,
#endif
UInt uiWidth,
UInt uiHeight,
UInt& uiAbsSum,
TextType eTType,
UInt uiAbsPartIdx,
Bool useTransformSkip
)
{
if (pcCU->getCUTransquantBypass(uiAbsPartIdx)) //!< 如果變換、量化過程被旁路,則直接將殘差pcResidual賦值給rpcCoeff
{ //!< 計算殘差絕對值的和並返回
uiAbsSum=0;
for (UInt k = 0; k<uiHeight; k++)
{
for (UInt j = 0; j<uiWidth; j++)
{
rpcCoeff[k*uiWidth+j]= pcResidual[k*uiStride+j];
uiAbsSum += abs(pcResidual[k*uiStride+j]);
}
}
return;
}
UInt uiMode; //luma intra pred
if(eTType == TEXT_LUMA && pcCU->getPredictionMode(uiAbsPartIdx) == MODE_INTRA )
{
uiMode = pcCU->getLumaIntraDir( uiAbsPartIdx ); //!< 獲取PU的幀內預測模式
}
else
{
uiMode = REG_DCT;
}
uiAbsSum = 0;
assert( (pcCU->getSlice()->getSPS()->getMaxTrSize() >= uiWidth) );
Int bitDepth = eTType == TEXT_LUMA ? g_bitDepthY : g_bitDepthC;
if(useTransformSkip) //!< TS模式
{
xTransformSkip(bitDepth, pcResidual, uiStride, m_plTempCoeff, uiWidth, uiHeight );
}
else
{
xT(bitDepth, uiMode, pcResidual, uiStride, m_plTempCoeff, uiWidth, uiHeight ); //!< m_plTempCoeff存放的是殘差經變換後的係數
}
xQuant( pcCU, m_plTempCoeff, rpcCoeff,
#if ADAPTIVE_QP_SELECTION
rpcArlCoeff,
#endif
uiWidth, uiHeight, uiAbsSum, eTType, uiAbsPartIdx ); //!< 量化,rpcCoeff存放最終結果
}
在Void TEncGOP::compressGOP中有這麼一段值得關注,主要對量化係數矩陣的值進行設置:
if(m_pcEncTop->getUseScalingListId() == SCALING_LIST_OFF) //!< ("ScalingList", m_useScalingListId, 0, "0: no scaling list, 1: default scaling lists, 2: scaling lists specified in ScalingListFile"),即默認程序會進入該條件體
{
m_pcEncTop->getTrQuant()->setFlatScalingList(); //!< 重點關注該函數的實現,即量化係數矩陣是如何賦值的
m_pcEncTop->getTrQuant()->setUseScalingList(false);
m_pcEncTop->getSPS()->setScalingListPresentFlag(false);
m_pcEncTop->getPPS()->setScalingListPresentFlag(false);
}
else if(m_pcEncTop->getUseScalingListId() == SCALING_LIST_DEFAULT)
{
pcSlice->setDefaultScalingList ();
m_pcEncTop->getSPS()->setScalingListPresentFlag(false);
m_pcEncTop->getPPS()->setScalingListPresentFlag(false);
m_pcEncTop->getTrQuant()->setScalingList(pcSlice->getScalingList());
m_pcEncTop->getTrQuant()->setUseScalingList(true);
}
else if(m_pcEncTop->getUseScalingListId() == SCALING_LIST_FILE_READ)
{
if(pcSlice->getScalingList()->xParseScalingList(m_pcCfg->getScalingListFile()))
{
pcSlice->setDefaultScalingList ();
}
pcSlice->getScalingList()->checkDcOfMatrix();
m_pcEncTop->getSPS()->setScalingListPresentFlag(pcSlice->checkDefaultScalingList());
m_pcEncTop->getPPS()->setScalingListPresentFlag(false);
m_pcEncTop->getTrQuant()->setScalingList(pcSlice->getScalingList());
m_pcEncTop->getTrQuant()->setUseScalingList(true);
}
else
{
printf("error : ScalingList == %d no support\n",m_pcEncTop->getUseScalingListId());
assert(0);
}
進入到ScalingList的設置函數中:
/** set flat matrix value to quantized coefficient
*/
Void TComTrQuant::setFlatScalingList()
{
UInt size,list;
UInt qp;
for(size=0;size<SCALING_LIST_SIZE_NUM;size++) //!< sizeID
{
for(list = 0; list < g_scalingListNum[size]; list++) //!< MatrixID
{
for(qp=0;qp<SCALING_LIST_REM_NUM;qp++) //!< 0~5
{
xsetFlatScalingList(list,size,qp);
setErrScaleCoeff(list,size,qp);
}
}
}
}
關注函數xsetFlatScalingList
Void TComTrQuant::xsetFlatScalingList(UInt list, UInt size, UInt qp)
{
UInt i,num = g_scalingListSize[size]; //!< 對應SizeID下Matrix的尺寸(行數乘列數),4x4,8x8,16x16,32x32
Int *quantcoeff;
Int *dequantcoeff;
Int quantScales = g_quantScales[qp]; //!< 26214,23302,20560,18396,16384,14564
Int invQuantScales = g_invQuantScales[qp]<<4; //!< 40,45,51,57,64,72
quantcoeff = getQuantCoeff(list, qp, size);
dequantcoeff = getDequantCoeff(list, qp, size);
for(i=0;i<num;i++) //!< 對Matrix中所有元素賦予相同的值,即所謂的"flat"
{
*quantcoeff++ = quantScales;
*dequantcoeff++ = invQuantScales;
}
}