HEVC函数入门(17)——编码一个CU

本文转载整理自http://blog.csdn.net/NB_vol_1/article/details/51152578,做了一些微调,这里也感谢这位博主的这篇博客,让我对CU的编码有了更深入的了解。
注意事项
1、帧间预测分为两种:merge模式(skip模式是一种特殊的merge模式)和AMVP模式(即普通的帧间预测模式);
2、merge模式只支持2Nx2N的划分。
3、 帧内预测只支持2Nx2N和NxN的划分模式
CU编码流程
一、先确定iMinQP和iMaxQP
这两个值可以从码率控制对象中得到,也可以自定义
二、如果是P、B类型的slice
1、先处理merge模式和AMVP模式的2Nx2N划分模式
通过一个循环遍历iMinQP到iMaxQP之间的所有QP,对每一个QP,尝试merge模式以及AMVP的2Nx2N模式,然后选出最优的模式。
2、处理AMVP剩余的划分模式
(1)处理NxN模式
(2)处理2NxN模式
(3)处理Nx2N模式
(4)测试AMP_ENC_SPEEDUP宏是否开启
(5)如果AMP_ENC_SPEEDUP宏开启
1)如果TestAMP_Hor、TestAMP_Ver(可以通过一个函数去检测)为真,那么处理2NxnU、2NxnD、nLx2N、nRx2N这四种模式:
①处理2NxnU模式
②处理2NxnD模式
③处理nLx2N模式
④处理nRx2N模式
2)如果TestAMP_Hor、TestAMP_Ver为假,但是定义了AMP_MRG宏,而且TestMergeAMP_Hor、TestMergeAMP_Ver(也可以通过函数去检测)为真,那么处 理 2NxnU、2NxnD、nLx2N、nRx2N这四种模式:
①处理2NxnU模式
②处理2NxnD模式
③处理nLx2N模式
④处理nRx2N模式
3)否则(即TestAMP_Hor、TestAMP_Ver为假,也没有定义AMP_MRG宏)不再处理2NxnU、2NxnD、nLx2N、nRx2N这四种模式。
(6)如果AMP_ENC_SPEEDUP宏没有开启,那么直接处理下面模式
①处理2NxnU模式
②处理2NxnD模式
③处理nLx2N模式
④处理nRx2N模式
这里的AMP是指PU的不对称分割,而①②③④中的UDLR可以用一张图理解:
这里写图片描述
三、如果是I类型的slice
那么处理帧内预测的两种模式:2Nx2N和NxN,这里注意BSlice和PSlice也可以进行帧内预测,具体请参考:http://blog.csdn.net/qq_21747841/article/details/73200806
四、尝试PCM模式
注意满足一定条件才会尝试PCM模式。
五、递归处理子CU
同样通过一个循环遍历iMinQP到iMaxQP之间的所有QP,对于每一个QP,递归调用xCompressCU。
六、通过比较选出最优的模式
下面是编码的流程图:
这里写图片描述
总结,其实xCompressCU的作用就是从LCU开始深度遍历,计算每一个depth上最优的模式,再综合比较各个depth上最优的模式,选出最优的模式
为了便于理解把xCompressCU的一些无关代码删除,下面是精简版的xCompressCU

#if AMP_ENC_SPEEDUP
Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth DEBUG_STRING_FN_DECLARE(sDebug_), PartSize eParentPartSize )//完成实际编码一个CU操作的是xCompressCU方法,CompressCU中调用的xCompressCU则相当于四叉树的根节点。
#else
Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth )
#endif
{//总结,其实xCompressCU的作用就是从LCU开始深度遍历,计算每一个depth上最优的模式,再综合比较各个depth上最优的模式,选出最优的模式
  TComPic* pcPic = rpcBestCU->getPic();
  DEBUG_STRING_NEW(sDebug)

  // get Original YUV data from picture
  m_ppcOrigYuv[uiDepth]->copyFromPicYuv( pcPic->getPicYuvOrg(), rpcBestCU->getCtuRsAddr(), rpcBestCU->getZorderIdxInCtu() );

    // variable for Early CU determination
  Bool    bSubBranch = true;

  // variable for Cbf fast mode PU decision
  Bool    doNotBlockPu = true;
  Bool    earlyDetectionSkipMode = false;

  Bool bBoundary = false;
  UInt uiLPelX   = rpcBestCU->getCUPelX();//getCUPelX返回CU的左上角的X坐标
  UInt uiRPelX   = uiLPelX + rpcBestCU->getWidth(0)  - 1;//getWidth(0)返回当前CU的宽度,参数是深度值,0表示返回的是当前CU的宽度,而不是其子CU的宽度
  UInt uiTPelY   = rpcBestCU->getCUPelY();
  UInt uiBPelY   = uiTPelY + rpcBestCU->getHeight(0) - 1;
 // Int A;
 // Int deltaQP_self = ((uiLPelX>=416 && uiLPelX <832) && (uiTPelY >= 240 && uiTPelY < 480)) ? 20 : 0;

 // Int deltaQP_self = 10;
  Int iBaseQP = xComputeQP( rpcBestCU, uiDepth ) ;  //调用xComputeQP得出基本的量化步长
  Int iMinQP;// 最小的步长  
  Int iMaxQP;// 最大的步长
  Bool isAddLowestQP = false;

  const UInt numberValidComponents = rpcBestCU->getPic()->getNumberValidComponents();

  if( (g_uiMaxCUWidth>>uiDepth) >= (g_uiMaxCUWidth >> ( rpcTempCU->getSlice()->getPPS()->getMaxCuDQPDepth())) )//使用了iBaseQP
  {
    Int idQP = m_pcEncCfg->getMaxDeltaQP();
    iMinQP = Clip3( -rpcTempCU->getSlice()->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP-idQP ) ;
    iMaxQP = Clip3( -rpcTempCU->getSlice()->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP+idQP ) ;
  }
  else
  {
    iMinQP = rpcTempCU->getQP(0);
    iMaxQP = rpcTempCU->getQP(0);
  }

  if ( m_pcEncCfg->getUseRateCtrl() )//使用速率控制,注意这里的QP使用了,码率控制对象计算出来的QP 通过QP,码率控制对象控制了编码器的比特率
  {
    iMinQP = m_pcRateCtrl->getRCQP() ;
    iMaxQP = m_pcRateCtrl->getRCQP() ;
  }
  //删除的无关代码
   TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx());
  // We need to split, so don't try these modes.
  if ( ( uiRPelX < rpcBestCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) &&
       ( uiBPelY < rpcBestCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
  {  // 此循环测试每一种量化步长,计算率失真,选出最优的QP 
    for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++)
    { 
      const Bool bIsLossless
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值