CU的划分、地址以及索引
在看HM源码的时候,最蛋疼的一件事就是被CU的划分以及它们的地址搞懵。为了搞清楚,仔细研究了一下源码,有什么错误请指出。为了弄清楚这个问题,必须要对扫描顺序、深度等概念有所理解。
扫描顺序
HEVC中对像素块的扫描方式有两种:Raster和Zscan
Raster扫描方式:从上到下,从左到右进行扫描,是最直观也是最容易理解的方式
Zscan扫描方式:因为CU是递归划分的,因此为了方便处理,HM中使用了Z扫描,也就是从左上角按照Z字形扫描到右下角。下面是Zscan扫描的一个例子:

CU的划分
CU按照四叉树的方式自上而下,进行递归划分,由于使用了这种递归的方式,因此HEVC中必须要使用Zscan的扫描方式。

深度
1、深度等于0时,CU的尺寸是64x64,该CU下面4x4小块的数量是256
2、深度等于1时,CU的尺寸是32x32,该CU下面4x4小块的数量是64
3、深度等于2时,CU的尺寸是16x16,该CU下面4x4小块的数量是16
4、深度等于3时,CU的尺寸是8x8,该CU下面4x4小块的数量是4
HEVC中对扫描顺序以及地址的处理
初始化扫描顺序
1、把每一个LCU都划分为4x4的小块,分别以Raster和Zscan的方式对4x4的小块进行编号(也就是索引)
2、把Raster到Zscan的编号映射存储在g_auiRasterToZscan数组中
3、把Zscan到Raster的编号映射存储在g_auiZscanToRaster数组中
4、把Raster索引到像素地址的映射放在g_auiRasterToPelX和g_auiRasterToPelY中
- extern UInt g_auiZscanToRaster[ MAX_NUM_SPU_W*MAX_NUM_SPU_W ];
- extern UInt g_auiRasterToZscan[ MAX_NUM_SPU_W*MAX_NUM_SPU_W ];
- Void initZscanToRaster ( Int iMaxDepth, Int iDepth, UInt uiStartVal, UInt*& rpuiCurrIdx );
- Void initRasterToZscan ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth );
- extern UInt g_auiRasterToPelX[ MAX_NUM_SPU_W*MAX_NUM_SPU_W ];
- extern UInt g_auiRasterToPelY[ MAX_NUM_SPU_W*MAX_NUM_SPU_W ];
- Void initRasterToPelXY ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth );
-
- Void initZscanToRaster ( Int iMaxDepth, Int iDepth, UInt uiStartVal, UInt*& rpuiCurrIdx )
- {
-
- Int iStride = 1 << ( iMaxDepth - 1 );
-
-
- if ( iDepth == iMaxDepth )
- {
- rpuiCurrIdx[0] = uiStartVal;
- rpuiCurrIdx++;
- }
- else
- {
-
- Int iStep = iStride >> iDepth;
- initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal, rpuiCurrIdx );
- initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal+iStep, rpuiCurrIdx );
- initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal+iStep*iStride, rpuiCurrIdx );
- initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal+iStep*iStride+iStep, rpuiCurrIdx );
- }
- }
- Void initRasterToZscan ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth )
- {
- UInt uiMinCUWidth = uiMaxCUWidth >> ( uiMaxDepth - 1 );
- UInt uiMinCUHeight = uiMaxCUHeight >> ( uiMaxDepth - 1 );
-
- UInt uiNumPartInWidth = (UInt)uiMaxCUWidth / uiMinCUWidth;
- UInt uiNumPartInHeight = (UInt)uiMaxCUHeight / uiMinCUHeight;
-
- for ( UInt i = 0; i < uiNumPartInWidth*uiNumPartInHeight; i++ )
- {
- g_auiRasterToZscan[ g_auiZscanToRaster[i] ] = i;
- }
- }
-
- Void initRasterToPelXY ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth )
- {
- UInt i;
-
- UInt* uiTempX = &g_auiRasterToPelX[0];
- UInt* uiTempY = &g_auiRasterToPelY[0];
-
- UInt uiMinCUWidth = uiMaxCUWidth >> ( uiMaxDepth - 1 );
- UInt uiMinCUHeight = uiMaxCUHeight >> ( uiMaxDepth - 1 );
-
- UInt uiNumPartInWidth = uiMaxCUWidth / uiMinCUWidth;
- UInt uiNumPartInHeight = uiMaxCUHeight / uiMinCUHeight;
-
- uiTempX[0] = 0; uiTempX++;
- for ( i = 1; i < uiNumPartInWidth; i++ )
- {
- uiTempX[0] = uiTempX[-1] + uiMinCUWidth; uiTempX++;
- }
- for ( i = 1; i < uiNumPartInHeight; i++ )
- {
- memcpy(uiTempX, uiTempX-uiNumPartInWidth, sizeof(UInt)*uiNumPartInWidth);
- uiTempX += uiNumPartInWidth;
- }
-
- for ( i = 1; i < uiNumPartInWidth*uiNumPartInHeight; i++ )
- {
- uiTempY[i] = ( i / uiNumPartInWidth ) * uiMinCUWidth;
- }
- };
根据扫描顺序得到地址
得到Zscan扫描顺序
这个很简单,由于CU是按照四叉树的方式进行递归处理的,因此CU被处理的顺序就是Zscan扫描顺序。下面是Zscan扫描顺序的一个示意图。

根据Zscan顺序得到Raster扫描顺序
得到Zscan扫描顺序之后还不够啊,我们需要知道某个块的地址才能对对它进行处理。获取地址需要Raster扫描顺序,可以直接使用g_auiZscanToRaster数组把Zscan顺序转换成Raster顺序。
根据Raster扫描顺序得到CU的地址
使用g_auiRasterToPelX和g_auiRasterToPelY就可以把Raster扫描顺序转换成相对地址了。但是这个地址只是4x4小块的地址,我们需要的是某个CU的地址,可以按照下面的方式进行处理:
1、开始的时候已知slice的起始地址、每个LCU的偏移地址,这些在初始化的时候都是确定。
2、根据CU左上角的4x4块的地址可以算出CU在图像中的地址了。
3、另外补充一点:根据深度可以确定CU的尺寸
在TEncCu中和CU有关的信息
TEncCu中有下面一些属性是需要注意的
- TComDataCU** m_ppcBestCU;
- TComDataCU** m_ppcTempCU;
- UChar m_uhTotalDepth;
- TComYuv** m_ppcPredYuvBest;
- TComYuv** m_ppcResiYuvBest;
- TComYuv** m_ppcRecoYuvBest;
- TComYuv** m_ppcPredYuvTemp;
- TComYuv** m_ppcResiYuvTemp;
- TComYuv** m_ppcRecoYuvTemp;
- TComYuv** m_ppcOrigYuv;
1、bestCU用于存放某个深度上CU的最优划分信息
2、tempCU用于编码过程,每编码完成一个CU就将tempCU与bestCU进行比较,如果有需要就更新bestCU
3、TComDataCU存放了CU中所有4x4小块的信息!
在编码过程中CU的地址和索引
LCU的地址
在函数compressCU中,LCU被初始化,它根据传进来的TComPicSym的LCU信息,调用initCU进行初始化,得到LCU的地址等信息。这么做是因为在编码的过程中不对TComPicSym的LCU进行直接操作,需要复制它的信息到临时的对象中,编码完成后再把最优的信息复制回TComPicSym中。
m_ppcBestCU表示某个深度下最优的CU信息,主要目的是存放最优的信息;m_ppcTempCU表示某个深度下临时的CU信息,它被用于编码操作,编码完成之后,再根据需要把最优信息保存到m_ppcBestCU中。
- Void TEncCu::compressCU( TComDataCU*& rpcCU )
- {
-
-
-
- m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
- m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
-
-
-
-
- xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 );
- }
1、开始的时候rpcCU表示一个LCU
2、利用LCU的信息,对深度等于0的bestCU和tempCU进行初始化,m_ppcBestCU的下标表示深度
3、调用xCompressCU
initCU主要用于LCU的初始化,普通CU的初始化不使用它
-
- Void TComDataCU::initCU( TComPic* pcPic, UInt iCUAddr )
- {
-
- m_pcPic = pcPic;
-
- m_pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx());
-
- m_uiCUAddr = iCUAddr;
-
- m_uiCUPelX = ( iCUAddr % pcPic->getFrameWidthInCU() ) * g_uiMaxCUWidth;
- m_uiCUPelY = ( iCUAddr / pcPic->getFrameWidthInCU() ) * g_uiMaxCUHeight;
- m_uiAbsIdxInLCU = 0;
-
- m_dTotalCost = MAX_DOUBLE;
-
- m_uiTotalDistortion = 0;
-
- m_uiTotalBits = 0;
-
- m_uiTotalBins = 0;
-
-
- m_uiNumPartition = pcPic->getNumPartInCU();
-
-
- for(Int i=0; igetNumPartInCU(); i++)
- {
- if(pcPic->getPicSym()->getInverseCUOrderMap(iCUAddr)*pcPic->getNumPartInCU()+i>=getSlice()->getSliceCurStartCUAddr())
- {
-
- m_sliceStartCU[i]=getSlice()->getSliceCurStartCUAddr();
- }
- else
- {
-
- m_sliceStartCU[i]=pcPic->getCU(getAddr())->m_sliceStartCU[i];
- }
- }
-
- for(Int i=0; igetNumPartInCU(); i++)
- {
- if(pcPic->getPicSym()->getInverseCUOrderMap(iCUAddr)*pcPic->getNumPartInCU()+i>=getSlice()->getSliceSegmentCurStartCUAddr())
- {
- m_sliceSegmentStartCU[i]=getSlice()->getSliceSegmentCurStartCUAddr();
- }
- else
- {
-
- m_sliceSegmentStartCU[i]=pcPic->getCU(getAddr())->m_sliceSegmentStartCU[i];
- }
- }
-
-
- Int partStartIdx = getSlice()->getSliceSegmentCurStartCUAddr() - pcPic->getPicSym()->getInverseCUOrderMap(iCUAddr) * pcPic->getNumPartInCU();
-
-
- Int numElements = min( partStartIdx, m_uiNumPartition );
- for ( Int ui = 0; ui < numElements; ui++ )
- {
- TComDataCU * pcFrom = pcPic->getCU(getAddr());
- m_skipFlag[ui] = pcFrom->getSkipFlag(ui);
- m_pePartSize[ui] = pcFrom->getPartitionSize(ui);
- m_pePredMode[ui] = pcFrom->getPredictionMode(ui);
- m_CUTransquantBypass[ui] = pcFrom->getCUTransquantBypass(ui);
- m_puhDepth[ui] = pcFrom->getDepth(ui);
- m_puhWidth [ui] = pcFrom->getWidth(ui);
- m_puhHeight [ui] = pcFrom->getHeight(ui);
- m_puhTrIdx [ui] = pcFrom->getTransformIdx(ui);
- m_puhTransformSkip[0][ui] = pcFrom->getTransformSkip(ui,TEXT_LUMA);
- m_puhTransformSkip[1][ui] = pcFrom->getTransformSkip(ui,TEXT_CHROMA_U);
- m_puhTransformSkip[2][ui] = pcFrom->getTransformSkip(ui,TEXT_CHROMA_V);
- m_apiMVPIdx[0][ui] = pcFrom->m_apiMVPIdx[0][ui];;
- m_apiMVPIdx[1][ui] = pcFrom->m_apiMVPIdx[1][ui];
- m_apiMVPNum[0][ui] = pcFrom->m_apiMVPNum[0][ui];
- m_apiMVPNum[1][ui] = pcFrom->m_apiMVPNum[1][ui];
- m_phQP[ui]=pcFrom->m_phQP[ui];
- m_pbMergeFlag[ui]=pcFrom->m_pbMergeFlag[ui];
- m_puhMergeIndex[ui]=pcFrom->m_puhMergeIndex[ui];
- m_puhLumaIntraDir[ui]=pcFrom->m_puhLumaIntraDir[ui];
- m_puhChromaIntraDir[ui]=pcFrom->m_puhChromaIntraDir[ui];
- m_puhInterDir[ui]=pcFrom->m_puhInterDir[ui];
- m_puhCbf[0][ui]=pcFrom->m_puhCbf[0][ui];
- m_puhCbf[1][ui]=pcFrom->m_puhCbf[1][ui];
- m_puhCbf[2][ui]=pcFrom->m_puhCbf[2][ui];
- m_pbIPCMFlag[ui] = pcFrom->m_pbIPCMFlag[ui];
- }
-
-
- Int firstElement = max( partStartIdx, 0 );
-
-
- numElements = m_uiNumPartition - firstElement;
-
- if ( numElements > 0 )
- {
- memset( m_skipFlag + firstElement, false, numElements * sizeof( *m_skipFlag ) );
-
- memset( m_pePartSize + firstElement, SIZE_NONE, numElements * sizeof( *m_pePartSize ) );
- memset( m_pePredMode + firstElement, MODE_NONE, numElements * sizeof( *m_pePredMode ) );
- memset( m_CUTransquantBypass+ firstElement, false, numElements * sizeof( *m_CUTransquantBypass) );
- memset( m_puhDepth + firstElement, 0, numElements * sizeof( *m_puhDepth ) );
- memset( m_puhTrIdx + firstElement, 0, numElements * sizeof( *m_puhTrIdx ) );
- memset( m_puhTransformSkip[0] + firstElement, 0, numElements * sizeof( *m_puhTransformSkip[0]) );
- memset( m_puhTransformSkip[1] + firstElement, 0, numElements * sizeof( *m_puhTransformSkip[1]) );
- memset( m_puhTransformSkip[2] + firstElement, 0, numElements * sizeof( *m_puhTransformSkip[2]) );
- memset( m_puhWidth + firstElement, g_uiMaxCUWidth, numElements * sizeof( *m_puhWidth ) );
- memset( m_puhHeight + firstElement, g_uiMaxCUHeight, numElements * sizeof( *m_puhHeight ) );
- memset( m_apiMVPIdx[0] + firstElement, -1, numElements * sizeof( *m_apiMVPIdx[0] ) );
- memset( m_apiMVPIdx[1] + firstElement, -1, numElements * sizeof( *m_apiMVPIdx[1] ) );
- memset( m_apiMVPNum[0] + firstElement, -1, numElements * sizeof( *m_apiMVPNum[0] ) );
- memset( m_apiMVPNum[1] + firstElement, -1, numElements * sizeof( *m_apiMVPNum[1] ) );
- memset( m_phQP + firstElement, getSlice()->getSliceQp(), numElements * sizeof( *m_phQP ) );
- memset( m_pbMergeFlag + firstElement, false, numElements * sizeof( *m_pbMergeFlag ) );
- memset( m_puhMergeIndex + firstElement, 0, numElements * sizeof( *m_puhMergeIndex ) );
- memset( m_puhLumaIntraDir + firstElement, DC_IDX, numElements * sizeof( *m_puhLumaIntraDir ) );
- memset( m_puhChromaIntraDir + firstElement, 0, numElements * sizeof( *m_puhChromaIntraDir ) );
- memset( m_puhInterDir + firstElement, 0, numElements * sizeof( *m_puhInterDir ) );
- memset( m_puhCbf[0] + firstElement, 0, numElements * sizeof( *m_puhCbf[0] ) );
- memset( m_puhCbf[1] + firstElement, 0, numElements * sizeof( *m_puhCbf[1] ) );
- memset( m_puhCbf[2] + firstElement, 0, numElements * sizeof( *m_puhCbf[2] ) );
- memset( m_pbIPCMFlag + firstElement, false, numElements * sizeof( *m_pbIPCMFlag ) );
- }
-
- UInt uiTmp = g_uiMaxCUWidth*g_uiMaxCUHeight;
- if ( 0 >= partStartIdx )
- {
- m_acCUMvField[0].clearMvField();
- m_acCUMvField[1].clearMvField();
- memset( m_pcTrCoeffY , 0, sizeof( TCoeff ) * uiTmp );
- #if ADAPTIVE_QP_SELECTION
- memset( m_pcArlCoeffY , 0, sizeof( Int ) * uiTmp );
- #endif
- memset( m_pcIPCMSampleY , 0, sizeof( Pel ) * uiTmp );
- uiTmp >>= 2;
- memset( m_pcTrCoeffCb, 0, sizeof( TCoeff ) * uiTmp );
- memset( m_pcTrCoeffCr, 0, sizeof( TCoeff ) * uiTmp );
- #if ADAPTIVE_QP_SELECTION
- memset( m_pcArlCoeffCb, 0, sizeof( Int ) * uiTmp );
- memset( m_pcArlCoeffCr, 0, sizeof( Int ) * uiTmp );
- #endif
- memset( m_pcIPCMSampleCb , 0, sizeof( Pel ) * uiTmp );
- memset( m_pcIPCMSampleCr , 0, sizeof( Pel ) * uiTmp );
- }
- else
- {
- TComDataCU * pcFrom = pcPic->getCU(getAddr());
- m_acCUMvField[0].copyFrom(&pcFrom->m_acCUMvField[0],m_uiNumPartition,0);
- m_acCUMvField[1].copyFrom(&pcFrom->m_acCUMvField[1],m_uiNumPartition,0);
- for(Int i=0; i
- {
- m_pcTrCoeffY[i]=pcFrom->m_pcTrCoeffY[i];
- #if ADAPTIVE_QP_SELECTION
- m_pcArlCoeffY[i]=pcFrom->m_pcArlCoeffY[i];
- #endif
- m_pcIPCMSampleY[i]=pcFrom->m_pcIPCMSampleY[i];
- }
- for(Int i=0; i<(uiTmp>>2); i++)
- {
- m_pcTrCoeffCb[i]=pcFrom->m_pcTrCoeffCb[i];
- m_pcTrCoeffCr[i]=pcFrom->m_pcTrCoeffCr[i];
- #if ADAPTIVE_QP_SELECTION
- m_pcArlCoeffCb[i]=pcFrom->m_pcArlCoeffCb[i];
- m_pcArlCoeffCr[i]=pcFrom->m_pcArlCoeffCr[i];
- #endif
- m_pcIPCMSampleCb[i]=pcFrom->m_pcIPCMSampleCb[i];
- m_pcIPCMSampleCr[i]=pcFrom->m_pcIPCMSampleCr[i];
- }
- }
-
-
-
- m_pcCULeft = NULL;
- m_pcCUAbove = NULL;
- m_pcCUAboveLeft = NULL;
- m_pcCUAboveRight = NULL;
-
-
- m_apcCUColocated[0] = NULL;
- m_apcCUColocated[1] = NULL;
-
-
- UInt uiWidthInCU = pcPic->getFrameWidthInCU();
-
-
-
-
- if ( m_uiCUAddr % uiWidthInCU )
- {
- m_pcCULeft = pcPic->getCU( m_uiCUAddr - 1 );
- }
-
-
- if ( m_uiCUAddr / uiWidthInCU )
- {
- m_pcCUAbove = pcPic->getCU( m_uiCUAddr - uiWidthInCU );
- }
-
-
- if ( m_pcCULeft && m_pcCUAbove )
- {
- m_pcCUAboveLeft = pcPic->getCU( m_uiCUAddr - uiWidthInCU - 1 );
- }
-
-
- if ( m_pcCUAbove && ( (m_uiCUAddr%uiWidthInCU) < (uiWidthInCU-1) ) )
- {
- m_pcCUAboveRight = pcPic->getCU( m_uiCUAddr - uiWidthInCU + 1 );
- }
-
-
- if ( getSlice()->getNumRefIdx( REF_PIC_LIST_0 ) > 0 )
- {
- m_apcCUColocated[0] = getSlice()->getRefPic( REF_PIC_LIST_0, 0)->getCU( m_uiCUAddr );
- }
-
- if ( getSlice()->getNumRefIdx( REF_PIC_LIST_1 ) > 0 )
- {
- m_apcCUColocated[1] = getSlice()->getRefPic( REF_PIC_LIST_1, 0)->getCU( m_uiCUAddr );
- }
- }
普通CU的地址
在xCompressCU中,下列语句用于初始化下一层的子CU
- UChar uhNextDepth = uiDepth+1;
- TComDataCU* pcSubBestPartCU = m_ppcBestCU[uhNextDepth];
- TComDataCU* pcSubTempPartCU = m_ppcTempCU[uhNextDepth];
-
-
-
-
-
- for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ )
- {
-
- pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );
-
- pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );
-
-
- }
普通的CU初始化的时候不使用initCU,而是以父亲CU作为参数调用initSubCU进行初始化。
1、计算当前CU在父亲CU中以partition(4x4大小的块)为单位的偏移
2、计算当前CU的地址,利用父亲CU的地址和偏移量可以算出当前CU的地址
3、计算当前CU在LCU中的Zscan顺序的索引,先获取父亲CU的Zscan索引,再加上偏移就可以得到当前CU的Zscan索引
4、计算当前CU的坐标,利用父亲CU的坐标、当前CU的尺寸和当前CU在父亲CU中的索引可以计算
5、最后请注意:LCU的相关信息通过initCU已经设置完成,因此对于32x32的CU,可以直接利用LCU调用initSubCU进行初始化!
- Void TComDataCU::initSubCU( TComDataCU* pcCU, UInt uiPartUnitIdx, UInt uiDepth, Int qp )
- {
- assert( uiPartUnitIdx<4 );
-
-
-
-
- UInt uiPartOffset = ( pcCU->getTotalNumPart()>>2 )*uiPartUnitIdx;
-
- m_pcPic = pcCU->getPic();
- m_pcSlice = m_pcPic->getSlice(m_pcPic->getCurrSliceIdx());
-
-
- m_uiCUAddr = pcCU->getAddr();
-
-
- m_uiAbsIdxInLCU = pcCU->getZorderIdxInCU() + uiPartOffset;
-
-
-
- m_uiCUPelX = pcCU->getCUPelX() + ( g_uiMaxCUWidth>>uiDepth )*( uiPartUnitIdx & 1 );
- m_uiCUPelY = pcCU->getCUPelY() + ( g_uiMaxCUHeight>>uiDepth )*( uiPartUnitIdx >> 1 );
-
- m_dTotalCost = MAX_DOUBLE;
- m_uiTotalDistortion = 0;
- m_uiTotalBits = 0;
- m_uiTotalBins = 0;
- m_uiNumPartition = pcCU->getTotalNumPart() >> 2;
-
- Int iSizeInUchar = sizeof( UChar ) * m_uiNumPartition;
- Int iSizeInBool = sizeof( Bool ) * m_uiNumPartition;
-
- Int sizeInChar = sizeof( Char ) * m_uiNumPartition;
- memset( m_phQP, qp, sizeInChar );
-
- memset( m_pbMergeFlag, 0, iSizeInBool );
- memset( m_puhMergeIndex, 0, iSizeInUchar );
- memset( m_puhLumaIntraDir, DC_IDX, iSizeInUchar );
- memset( m_puhChromaIntraDir, 0, iSizeInUchar );
- memset( m_puhInterDir, 0, iSizeInUchar );
- memset( m_puhTrIdx, 0, iSizeInUchar );
- memset( m_puhTransformSkip[0], 0, iSizeInUchar );
- memset( m_puhTransformSkip[1], 0, iSizeInUchar );
- memset( m_puhTransformSkip[2], 0, iSizeInUchar );
- memset( m_puhCbf[0], 0, iSizeInUchar );
- memset( m_puhCbf[1], 0, iSizeInUchar );
- memset( m_puhCbf[2], 0, iSizeInUchar );
- memset( m_puhDepth, uiDepth, iSizeInUchar );
-
- UChar uhWidth = g_uiMaxCUWidth >> uiDepth;
- UChar uhHeight = g_uiMaxCUHeight >> uiDepth;
- memset( m_puhWidth, uhWidth, iSizeInUchar );
- memset( m_puhHeight, uhHeight, iSizeInUchar );
- memset( m_pbIPCMFlag, 0, iSizeInBool );
- for (UInt ui = 0; ui < m_uiNumPartition; ui++)
- {
- m_skipFlag[ui] = false;
- m_pePartSize[ui] = SIZE_NONE;
- m_pePredMode[ui] = MODE_NONE;
- m_CUTransquantBypass[ui] = false;
- m_apiMVPIdx[0][ui] = -1;
- m_apiMVPIdx[1][ui] = -1;
- m_apiMVPNum[0][ui] = -1;
- m_apiMVPNum[1][ui] = -1;
- if(m_pcPic->getPicSym()->getInverseCUOrderMap(getAddr())*m_pcPic->getNumPartInCU()+m_uiAbsIdxInLCU+uigetSliceSegmentCurStartCUAddr())
- {
- m_apiMVPIdx[0][ui] = pcCU->m_apiMVPIdx[0][uiPartOffset+ui];
- m_apiMVPIdx[1][ui] = pcCU->m_apiMVPIdx[1][uiPartOffset+ui];;
- m_apiMVPNum[0][ui] = pcCU->m_apiMVPNum[0][uiPartOffset+ui];;
- m_apiMVPNum[1][ui] = pcCU->m_apiMVPNum[1][uiPartOffset+ui];;
- m_puhDepth [ui] = pcCU->getDepth(uiPartOffset+ui);
- m_puhWidth [ui] = pcCU->getWidth(uiPartOffset+ui);
- m_puhHeight [ui] = pcCU->getHeight(uiPartOffset+ui);
- m_puhTrIdx [ui] = pcCU->getTransformIdx(uiPartOffset+ui);
- m_puhTransformSkip[0][ui] = pcCU->getTransformSkip(uiPartOffset+ui,TEXT_LUMA);
- m_puhTransformSkip[1][ui] = pcCU->getTransformSkip(uiPartOffset+ui,TEXT_CHROMA_U);
- m_puhTransformSkip[2][ui] = pcCU->getTransformSkip(uiPartOffset+ui,TEXT_CHROMA_V);
- m_skipFlag[ui] = pcCU->getSkipFlag(uiPartOffset+ui);
- m_pePartSize[ui] = pcCU->getPartitionSize(uiPartOffset+ui);
- m_pePredMode[ui] = pcCU->getPredictionMode(uiPartOffset+ui);
- m_CUTransquantBypass[ui] = pcCU->getCUTransquantBypass(uiPartOffset+ui);
- m_pbIPCMFlag[ui]=pcCU->m_pbIPCMFlag[uiPartOffset+ui];
- m_phQP[ui] = pcCU->m_phQP[uiPartOffset+ui];
- m_pbMergeFlag[ui]=pcCU->m_pbMergeFlag[uiPartOffset+ui];
- m_puhMergeIndex[ui]=pcCU->m_puhMergeIndex[uiPartOffset+ui];
- m_puhLumaIntraDir[ui]=pcCU->m_puhLumaIntraDir[uiPartOffset+ui];
- m_puhChromaIntraDir[ui]=pcCU->m_puhChromaIntraDir[uiPartOffset+ui];
- m_puhInterDir[ui]=pcCU->m_puhInterDir[uiPartOffset+ui];
- m_puhCbf[0][ui]=pcCU->m_puhCbf[0][uiPartOffset+ui];
- m_puhCbf[1][ui]=pcCU->m_puhCbf[1][uiPartOffset+ui];
- m_puhCbf[2][ui]=pcCU->m_puhCbf[2][uiPartOffset+ui];
-
- }
- }
- UInt uiTmp = uhWidth*uhHeight;
- memset( m_pcTrCoeffY , 0, sizeof(TCoeff)*uiTmp );
- #if ADAPTIVE_QP_SELECTION
- memset( m_pcArlCoeffY , 0, sizeof(Int)*uiTmp );
- #endif
- memset( m_pcIPCMSampleY , 0, sizeof( Pel ) * uiTmp );
- uiTmp >>= 2;
- memset( m_pcTrCoeffCb, 0, sizeof(TCoeff)*uiTmp );
- memset( m_pcTrCoeffCr, 0, sizeof(TCoeff)*uiTmp );
- #if ADAPTIVE_QP_SELECTION
- memset( m_pcArlCoeffCb, 0, sizeof(Int)*uiTmp );
- memset( m_pcArlCoeffCr, 0, sizeof(Int)*uiTmp );
- #endif
- memset( m_pcIPCMSampleCb , 0, sizeof( Pel ) * uiTmp );
- memset( m_pcIPCMSampleCr , 0, sizeof( Pel ) * uiTmp );
- m_acCUMvField[0].clearMvField();
- m_acCUMvField[1].clearMvField();
-
- if(m_pcPic->getPicSym()->getInverseCUOrderMap(getAddr())*m_pcPic->getNumPartInCU()+m_uiAbsIdxInLCUgetSliceSegmentCurStartCUAddr())
- {
-
- UInt uiMaxCuWidth=pcCU->getSlice()->getSPS()->getMaxCUWidth();
- UInt uiMaxCuHeight=pcCU->getSlice()->getSPS()->getMaxCUHeight();
- TComDataCU * bigCU = getPic()->getCU(getAddr());
- Int minui = uiPartOffset;
- minui = -minui;
- pcCU->m_acCUMvField[0].copyTo(&m_acCUMvField[0],minui,uiPartOffset,m_uiNumPartition);
- pcCU->m_acCUMvField[1].copyTo(&m_acCUMvField[1],minui,uiPartOffset,m_uiNumPartition);
- UInt uiCoffOffset = uiMaxCuWidth*uiMaxCuHeight*m_uiAbsIdxInLCU/pcCU->getPic()->getNumPartInCU();
- uiTmp = uhWidth*uhHeight;
- for(Int i=0; i
- {
- m_pcTrCoeffY[i]=bigCU->m_pcTrCoeffY[uiCoffOffset+i];
- #if ADAPTIVE_QP_SELECTION
- m_pcArlCoeffY[i]=bigCU->m_pcArlCoeffY[uiCoffOffset+i];
- #endif
- m_pcIPCMSampleY[i]=bigCU->m_pcIPCMSampleY[uiCoffOffset+i];
- }
- uiTmp>>=2;
- uiCoffOffset>>=2;
- for(Int i=0; i
- {
- m_pcTrCoeffCr[i]=bigCU->m_pcTrCoeffCr[uiCoffOffset+i];
- m_pcTrCoeffCb[i]=bigCU->m_pcTrCoeffCb[uiCoffOffset+i];
- #if ADAPTIVE_QP_SELECTION
- m_pcArlCoeffCr[i]=bigCU->m_pcArlCoeffCr[uiCoffOffset+i];
- m_pcArlCoeffCb[i]=bigCU->m_pcArlCoeffCb[uiCoffOffset+i];
- #endif
- m_pcIPCMSampleCb[i]=bigCU->m_pcIPCMSampleCb[uiCoffOffset+i];
- m_pcIPCMSampleCr[i]=bigCU->m_pcIPCMSampleCr[uiCoffOffset+i];
- }
- }
-
- m_pcCULeft = pcCU->getCULeft();
- m_pcCUAbove = pcCU->getCUAbove();
- m_pcCUAboveLeft = pcCU->getCUAboveLeft();
- m_pcCUAboveRight = pcCU->getCUAboveRight();
-
- m_apcCUColocated[0] = pcCU->getCUColocated(REF_PIC_LIST_0);
- m_apcCUColocated[1] = pcCU->getCUColocated(REF_PIC_LIST_1);
- memcpy(m_sliceStartCU,pcCU->m_sliceStartCU+uiPartOffset,sizeof(UInt)*m_uiNumPartition);
- memcpy(m_sliceSegmentStartCU,pcCU->m_sliceSegmentStartCU+uiPartOffset,sizeof(UInt)*m_uiNumPartition);
- }
在xCompressCU中,下面四条语句用于获取bestCU的坐标
- UInt uiLPelX = rpcBestCU->getCUPelX();
- UInt uiRPelX = uiLPelX + rpcBestCU->getWidth(0) - 1;
- UInt uiTPelY = rpcBestCU->getCUPelY();
- UInt uiBPelY = uiTPelY + rpcBestCU->getHeight(0) - 1;
1、getCUPelX返回CU的左上角的X坐标
2、getWidth(0)返回当前CU的宽度,参数是深度值,0表示返回的是当前CU的宽度,而不是其子CU的宽度
3、getCUPelY返回CU左上角的Y坐标
4、getHeight(0)返回当前CU的高度,参数是深度值,0表示返回的是当前CU的高度,而不是其子CU的高度