今天来学习xT
和xTrMxN
和xTrMxN_EMT
函数。
在之前的 H.266代码学习:transformNxN函数 中提到JEM变换分为两次:主变换+二次NSST。transformNxN
会调用xT
进行主变换。
在JEM中,主变换有三种:
1.原HEVC中的DCT-2/4x4 DST。
2.多核变换。
3.KLT变换。
其中1和3的入口函数为xTrMxN
,2的入口函数为xTrMxN_EMT
。
当然,有变换就有反变换,三者对应的反变换函数分别是:xIT
、xITrMxN
、xITrMxN_EMT
。
xT
下面先来看xT
,它是主变换的入口函数。 函数体很短,比较简单。
HEVC代码学习36:xTrMxN函数中对HM中的xT
进行了学习。
JEM中与HM主要区别:
在JEM中,在原HEVC中的DCT-2/4x4 DST基础上增加了多核变换和KLT变换,xT
增加了多核变换的入口函数xTrMxN_EMT
,而KLT变换的入口函数放在了xTrMxN
中,之后会具体学习。
流程如下:
一、读取残差
二、如果变换模式ucTrIdx
不是DCT2_HEVC
且KLT为false时,执行1,否则执行2
1.调用xTrMxN_EMT
进行多核变换。
2.调用xTrMxN
进行DCT-2/4x4 DST和KLT变换。
代码分析:
/** Wrapper function between HM interface and core NxN forward transform (2D)
* \param channelBitDepth bit depth of channel
* \param useDST
* \param piBlkResi input data (residual)
* \param uiStride stride of input residual data
* \param psCoeff output data (transform coefficients)
* \param iWidth transform width
* \param iHeight transform height
* \param maxLog2TrDynamicRange
*/
//变换函数
Void TComTrQuant::xT( const Int channelBitDepth, Bool useDST, Pel* piBlkResi, UInt uiStride, TCoeff* psCoeff, Int iWidth, Int iHeight, const Int maxLog2TrDynamicRange
#if COM16_C806_EMT
, UChar ucMode
, UChar ucTrIdx
#endif
#if VCEG_AZ08_KLT_COMMON
, Bool useKLT //KLT flag
#endif
)
{
#if MATRIX_MULT
if( iWidth == iHeight)
{
#if COM16_C806_EMT
if( ucTrIdx!=DCT2_HEVC )
{
xTr_EMT(channelBitDepth, piBlkResi, psCoeff, uiStride, (UInt)iWidth, useDST, maxLog2TrDynamicRange, ucMode, ucTrIdx );
}
else
#endif
xTr(channelBitDepth, piBlkResi, psCoeff, uiStride, (UInt)iWidth, useDST, maxLog2TrDynamicRange);
return;
}
#endif
TCoeff block[ MAX_TU_SIZE * MAX_TU_SIZE ];
TCoeff coeff[ MAX_TU_SIZE * MAX_TU_SIZE ];
for (Int y = 0; y < iHeight; y++)
{
for (Int x = 0; x < iWidth; x++)
{
block[(y * iWidth) + x] = piBlkResi[(y * uiStride) + x]; //读取残差
}
}
#if COM16_C806_EMT
#if VCEG_AZ08_KLT_COMMON
if( ucTrIdx!=DCT2_HEVC && useKLT == false) //不是DCT-2且KLT为false时,使用EMT
#else
if( ucTrIdx!=DCT2_HEVC )
#endif
{
xTrMxN_EMT(channelBitDepth, block, coeff, iWidth, iHeight, useDST, maxLog2TrDynamicRange, ucMode, ucTrIdx );
}
else //否则使用DCT-2或KLT
#endif
#if VCEG_AZ08_KLT_COMMON
xTrMxN( channelBitDepth, block, coeff, iWidth, iHeight, useDST, maxLog2TrDynamicRange, useK