HEVC代码学习25:xDecompressCU函数

来源:互联网 发布:挑战韩网络加速器 编辑:程序博客网 时间:2024/05/21 01:45

今天来看解码端的xDecompressCU函数。对应x
CompressCU,解码端有xDecompressCU函数,来完成CU的划分即各CU模式的选择。

相比编码端,解码端就简单多了,只需要按照编码端传递的参数来进行划分即可,不需要在进行复杂的选择。

主要流程如下:
1、初始化,读取各种信息
2、判断是否越界
3、当深度小于CU最大深度和设定的最大深度且不越界时,递归调用xDecompressCU。
4、清空残差,复制子块图像。
5、选择预测模式,构造预测块。
6、复制得到重构快。

从这里我们可以看到,编码器会传递CU深度和预测模式给解码器。

Void TDecCu::xDecompressCU( TComDataCU* pCtu, UInt uiAbsPartIdx,  UInt uiDepth ){  TComPic* pcPic = pCtu->getPic();  TComSlice * pcSlice = pCtu->getSlice();  const TComSPS &sps=*(pcSlice->getSPS());  Bool bBoundary = false;  UInt uiLPelX   = pCtu->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];  UInt uiRPelX   = uiLPelX + (sps.getMaxCUWidth()>>uiDepth)  - 1;  UInt uiTPelY   = pCtu->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];  UInt uiBPelY   = uiTPelY + (sps.getMaxCUHeight()>>uiDepth) - 1;  if( ( uiRPelX >= sps.getPicWidthInLumaSamples() ) || ( uiBPelY >= sps.getPicHeightInLumaSamples() ) )     //检测是否越界  {    bBoundary = true;  }  //当小于CU最大深度和设定的最大深度,且未越界时,递归调用xDecompressCU  if( ( ( uiDepth < pCtu->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary )  {    UInt uiNextDepth = uiDepth + 1;    UInt uiQNumParts = pCtu->getTotalNumPart() >> (uiNextDepth<<1);    UInt uiIdx = uiAbsPartIdx;    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++ )    {      uiLPelX = pCtu->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];      uiTPelY = pCtu->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];      if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) )      {        xDecompressCU(pCtu, uiIdx, uiNextDepth );      }      uiIdx += uiQNumParts;    }    return;  }  // Residual reconstruction  m_ppcYuvResi[uiDepth]->clear();       //清空残差  m_ppcCU[uiDepth]->copySubCU( pCtu, uiAbsPartIdx );        //复制子块信息  switch( m_ppcCU[uiDepth]->getPredictionMode(0) )      //选择预测模式  {    case MODE_INTER:        //帧间预测      xReconInter( m_ppcCU[uiDepth], uiDepth );      break;    case MODE_INTRA:        //帧内预测      xReconIntraQT( m_ppcCU[uiDepth], uiDepth );      break;    default:      assert(0);      break;  }#if DEBUG_STRING        //默认关闭,用于打印选择的预测模式  const PredMode predMode=m_ppcCU[uiDepth]->getPredictionMode(0);  if (DebugOptionList::DebugString_Structure.getInt()&DebugStringGetPredModeMask(predMode))  {    PartSize eSize=m_ppcCU[uiDepth]->getPartitionSize(0);    std::ostream &ss(std::cout);    ss <<"###: " << (predMode==MODE_INTRA?"Intra   ":"Inter   ") << partSizeToString[eSize] << " CU at " << m_ppcCU[uiDepth]->getCUPelX() << ", " << m_ppcCU[uiDepth]->getCUPelY() << " width=" << UInt(m_ppcCU[uiDepth]->getWidth(0)) << std::endl;  }#endif  if ( m_ppcCU[uiDepth]->isLosslessCoded(0) && (m_ppcCU[uiDepth]->getIPCMFlag(0) == false))  {    xFillPCMBuffer(m_ppcCU[uiDepth], uiDepth);      //填充PCM Buffer  }  xCopyToPic( m_ppcCU[uiDepth], pcPic, uiAbsPartIdx, uiDepth );     //复制得到重构快}