之前已经对MDNSST理论知识进行了学习,这里不再赘述,来初步看代码部分。
http://blog.csdn.net/lin453701006/article/details/79030862
MDNSST是在主变换后进行处理,在transformNxN函数中,可以看到,经过xT主变换后会进行NSST变换,这里只分析其中MDNSST相关代码,为了便于阅读,省略其他代码。
MDNSST主要流程如下:
1.获取NSST索引,索引与分块索引有关,随外层PU分块情况循环,不是直接根据NSST索引进行循环(这里没太搞懂,与之前理论学习有些出入)。
2.初始化NSST相关参数,根据TU尺寸确定变换区域。
3.获取帧内预测模式,当为色度LM模式时,模式索引置为PLANAR索引。
4.根据TU尺寸选择HyGT算法,调用FwdNsst8x8或FwdNsst4x4进行变换。
5.变换后的系数按扫描顺序重新排成矩阵。
其中NSST索引直接借用了所替代的ROT索引。具体变换是通过FwdNsst8x8或FwdNsst4x4进行,这两个函数不具体研究了。
Void TComTrQuant::transformNxN( TComTU & rTu,
const ComponentID compID,
Pel * pcResidual,
const UInt uiStride,
TCoeff * rpcCoeff,
#if ADAPTIVE_QP_SELECTION
TCoeff * pcArlCoeff,
#endif
TCoeff & uiAbsSum,
const QpParam & cQP
#if VCEG_AZ08_KLT_COMMON
, Bool useKLT
#endif
)
{
/*****省略初始化代码*****/
/*****省略rdpcm*****/
rdpcmNxN();
if (rdpcmMode == RDPCM_OFF)
{
uiAbsSum = 0;
//transform and quantise
if(pcCU->getCUTransquantBypass(uiAbsPartIdx))
{
/*****省略旁路变换量化处理*****/
}
else
{
/*****省略无关代码*****/
if(pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0)
{
/*****省略xTransformSkip*****/
xTransformSkip();
}
else
{
/*****省略主变换*****/
xT();
}
/*****省略无关代码*****/
/***********************MDNSST************************/
#elif COM16_C1044_NSST //MDNSST
#if JVET_C0024_QTBT
Char ucNsstIdx = pcCU->getROTIdx(toChannelType(compID), uiAbsPartIdx) ; //NSST索引
if (ucNsstIdx && uiWidth>=4 && uiHeight>=4 //当ucNsstIdx非0且块尺寸大于等于4时可用
#if JVET_C0045_C0053_NO_NSST_FOR_TS
&& !pcCU->getTransformSkip(uiAbsPartIdx, compID) //Transform skip下NSST不可用
#endif
)
#else
if (pcCU->getROTIdx(uiAbsPartIdx)
#if JVET_C0045_C0053_NO_NSST_FOR_TS
&& !pcCU->getTransformSkip(uiAbsPartIdx, compID)
#endif
)
#endif
{
#if JVET_D0120_NSST_IMPROV
static Int NSST_MATRIX[64]; //8x8
//4x4 TU用4x4 NSST,大于4x4的用8x8 NSST
const Int iLog2SbSize = (uiWidth > 4 && uiHeight > 4) ? 3 : 2;
const Int iSbSize = (uiWidth > 4 && uiHeight > 4) ? 8 : 4;