[HEVC] HEVC学习(六) —— 帧内预测系列之四(下)
本帖最后由 cjl2011 于 2012-11-19 07:10 PM 编辑 //===== check modes (using r-d costs) ===== //! 帧内预测模式最佳值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出 //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做 //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到最佳预测模式(在HM9.0中会得到包括次优解在内的两个 //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对最佳(及次优)预测模式的所有分割模式遍历一遍, //! 得到最终的最佳结果 #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiSecondBestMode = MAX_UINT; Double dSecondBestPUCost = MAX_DOUBLE; #endif UInt uiBestPUMode = 0; //!< 存放最佳预测模式 UInt uiBestPUDistY = 0; //!< 存放最佳预测模式对应的亮度失真值 UInt uiBestPUDistC = 0; //!< 存放最佳预测模式对应的色度失真值 Double dBestPUCost = MAX_DOUBLE; //!< 存放最佳预测模式对应的总代价 for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) //!< 遍历存储在uiRdModeList里的模式 { // set luma prediction mode UInt uiOrgMode = uiRdModeList[uiMode]; pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); // set context models if( m_bUseSBACRD ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); } // determine residual for partition UInt uiPUDistY = 0; //!< 存放当前预测模式对应的亮度失真值 UInt uiPUDistC = 0; //!< 存放当前预测模式对应的色度失真值 Double dPUCost = 0.0; //!< 存放当前预测模式对应的代价 #if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, true, dPUCost ); #else xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, dPUCost ); #endif // check r-d cost if( dPUCost < dBestPUCost ) //!< 更新最佳预测模式相关参数 { #if HHI_RQT_INTRA_SPEEDUP_MOD uiSecondBestMode = uiBestPUMode; dSecondBestPUCost = dBestPUCost; #endif uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; uiBestPUDistC = uiPUDistC; dBestPUCost = dPUCost; xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv ); UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 ); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); } #if HHI_RQT_INTRA_SPEEDUP_MOD else if( dPUCost < dSecondBestPUCost ) { uiSecondBestMode = uiOrgMode; dSecondBestPUCost = dPUCost; } #endif } // Mode loop #if HHI_RQT_INTRA_SPEEDUP #if HHI_RQT_INTRA_SPEEDUP_MOD for( UInt ui =0; ui < 2; ++ui ) #endif { #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiOrgMode = ui ? uiSecondBestMode : uiBestPUMode; if( uiOrgMode == MAX_UINT ) { break; } #else UInt uiOrgMode = uiBestPUMode; //!< 设置模式为最佳预测模式 #endif pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); // set context models if( m_bUseSBACRD ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); } // determine residual for partition UInt uiPUDistY = 0; UInt uiPUDistC = 0; Double dPUCost = 0.0; //! 注意该函数倒数第二个参数,此时为false xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost ); // check r-d cost if( dPUCost < dBestPUCost ) { uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; uiBestPUDistC = uiPUDistC; dBestPUCost = dPUCost; xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv ); UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 ); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); } } // Mode loop #endif |