CodingStructure类中的各个函数对于cu、pu和tu的函数处理,其实大致流程都是差不多一样的,所以这里只对cu的相应函数进行分析。
对于下面CodingStructure类中的各个函数的阅读,可以很深刻的理解各种数据的存取规则到底是怎样的,也能更深刻的理解CodingStructure类中各成员变量的意义。
//根据所给pos获取cs中对应位置的cu
CodingUnit* CodingStructure::getCU( const Position &pos, const ChannelType effChType )
{
const CompArea &_blk = area.blocks[effChType]; //当前cs所处理的区域
if( !_blk.contains( pos ) ) //所给pos是否在当前cs的区域内
{
if( parent ) return parent->getCU( pos, effChType ); //如果pos不在cs区域内,那么向上一级回溯到父节点cs,继续获取对应位置cu
else return nullptr;
}
else
{
//rsAddr()函数获取pos在cs.area中的相对位置 m_cuIdx中存储cu在cs.cus中的对应索引号
const unsigned idx = m_cuIdx[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
if( idx != 0 ) return cus[ idx - 1 ];
else return nullptr;
}
}
//cs中添加一个cu
CodingUnit& CodingStructure::addCU( const UnitArea &unit, const ChannelType chType )
{
CodingUnit *cu = m_cuCache.get();
cu->UnitArea::operator=( unit ); //创建一个cu,并初始化
cu->initData();
cu->cs = this;
cu->slice = nullptr;
cu->next = nullptr;
cu->firstPU = nullptr;
cu->lastPU = nullptr;
cu->firstTU = nullptr;
cu->lastTU = nullptr;
cu->chType = chType;
CodingUnit *prevCU = m_numCUs > 0 ? cus.back() : nullptr; //新cu要插入cus的末尾,所以获取前一个cu
if( prevCU )
{
prevCU->next = cu;
#if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
CHECK( prevCU->cacheId != cu->cacheId, "Inconsintent cacheId between previous and current CU" );
#endif
}
cus.push_back( cu ); //入栈
UInt idx = ++m_numCUs; //cu的索引,也就是m_cuIdx中需要存储的值
cu->idx = idx;
UInt numCh = ::getNumberValidChannels( area.chromaFormat );
for( UInt i = 0; i < numCh; i++ )
{
if( !cu->blocks[i].valid() )
{
continue;
}
const CompArea &_selfBlk = area.blocks[i]; //获取当前cs以及cu分别的area
const CompArea &_blk = cu-> blocks[i];
const UnitScale& scale = unitScale[_blk.compID];
const Area scaledSelf = scale.scale( _selfBlk );
const Area scaledBlk = scale.scale( _blk ); //按照VTM最小处理单元,将area的像素值,scale转化为最小单元值
unsigned *idxPtr = m_cuIdx[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width ); //获取应该修改的m_cuIdx的起始地址
CHECK( *idxPtr, "Overwriting a pre-existing value, should be '0'!" );
AreaBuf<UInt>( idxPtr, scaledSelf.width, scaledBlk.size() ).fill( idx ); //将cs区域内的cu区域的m_cuIdx填充idx索引值
}
return<