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;
}
}