HM代码阅读:帧内预测(一)
来源:互联网 发布:yum erase remove区别 编辑:程序博客网 时间:2024/05/21 14:53
本文的代码均是TEncSearch::estIntraPredLumaQT函数或被它调用的函数中的代码。在TEncSearch::estIntraPredLumaQT函数中,首先确定RMD(Rough Mode Decision)候选。RMD的候选模式的个数由以下两个数组确定:
const UChar g_aucIntraModeNumFast_UseMPM[MAX_CU_DEPTH] ={ 3, // 2x2 8, // 4x4 8, // 8x8 3, // 16x16 3, // 32x32 3 // 64x64};const UChar g_aucIntraModeNumFast_NotUseMPM[MAX_CU_DEPTH] ={ 3, // 2x2 9, // 4x4 9, // 8x8 4, // 16x16 33 4, // 32x32 33 5 // 64x64 33};
从上面两个数组可以看出,RMD模式的个数与PU的大小有关。PU较小(4x4或8x8)时,RMD个数为8;PU较大(16x16或32x32或64x64)时,RMD个数为3。选择RMD时,uiMode按代价uiCost在CandCostList中从小到大排列在CandModeList中。
UInt TEncSearch::xUpdateCandList( UInt uiMode, Double uiCost, UInt uiFastCandNum, UInt * CandModeList, Double * CandCostList ){ UInt i; UInt shift=0; // 确定插入位置shift(从右至左) while ( shift<uiFastCandNum && uiCost<CandCostList[ uiFastCandNum-1-shift ] ) { shift++; } if( shift!=0 ) { // 插入点及之后的模式号外后挪 for(i=1; i<shift; i++) { CandModeList[ uiFastCandNum-i ] = CandModeList[ uiFastCandNum-1-i ]; CandCostList[ uiFastCandNum-i ] = CandCostList[ uiFastCandNum-1-i ]; } // 在插入点插入相应的模式号 CandModeList[ uiFastCandNum-shift ] = uiMode; CandCostList[ uiFastCandNum-shift ] = uiCost; return 1; } return 0;}
上面函数的返回值用作TEncSearch::estIntraPredLumaQT中定义的变量CandNum的增量,然而CandNum的值没有被使用,因此上面函数的返回值是没有用处的。CandCostList以从小到大的顺序,往后挪时,会把cost最大的模式覆盖掉,这样做是合理。
RMO后,再加入MPM(most probable mode)模式。如果MPM模式不在RMO产生的集合里,则加入MPM模式。
if (m_pcEncCfg->getFastUDIUseMPMEnabled()) { Int uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1}; Int iMode = -1; pcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode ); // 获取MPM模式 // MPM模式的个数 const Int numCand = ( iMode >= 0 ) ? iMode : Int(NUM_MOST_PROBABLE_MODES); for( Int j=0; j < numCand; j++) { Bool mostProbableModeIncluded = false; Int mostProbableMode = uiPreds[j]; for( Int i=0; i < numModesForFullRD; i++) { mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); } if (!mostProbableModeIncluded) { uiRdModeList[numModesForFullRD++] = mostProbableMode; } } }
获取MPM模式的代码如下(在指针piMode指向的变量中赋MPM的个数):
/** Get most probable intra modes*\param uiAbsPartIdx partition index*\param uiIntraDirPred pointer to the array for MPM storage*\param compID colour component ID*\param piMode it is set with MPM mode in case both MPM are equal. It is used to restrict RD search at encode side.*\returns Number of MPM*/Void TComDataCU::getIntraDirPredictor( UInt uiAbsPartIdx, Int uiIntraDirPred[NUM_MOST_PROBABLE_MODES], const ComponentID compID, Int* piMode ) const{ UInt LeftPartIdx = MAX_UINT; UInt AbovePartIdx = MAX_UINT; Int iLeftIntraDir, iAboveIntraDir; const TComSPS *sps=getSlice()->getSPS(); const UInt partsPerMinCU = 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize())); const ChannelType chType = toChannelType(compID); const ChromaFormat chForm = getPic()->getChromaFormat(); // Get intra direction of left PU const TComDataCU *pcCULeft = getPULeft( LeftPartIdx, m_absZIdxInCtu + uiAbsPartIdx ); if (isChroma(compID)) { LeftPartIdx = getChromasCorrespondingPULumaIdx(LeftPartIdx, chForm, partsPerMinCU); } // 若左边PU不是Intra块,则赋为DC模式:Any unavailable prediction mode is considered to be Intra_DC. iLeftIntraDir = pcCULeft ? ( pcCULeft->isIntra( LeftPartIdx ) ? pcCULeft->getIntraDir( chType, LeftPartIdx ) : DC_IDX ) : DC_IDX; // Get intra direction of above PU const TComDataCU *pcCUAbove = getPUAbove( AbovePartIdx, m_absZIdxInCtu + uiAbsPartIdx, true, true ); if (isChroma(compID)) { AbovePartIdx = getChromasCorrespondingPULumaIdx(AbovePartIdx, chForm, partsPerMinCU); } // 若上边PU不是Intra块,则赋为DC模式:Any unavailable prediction mode is considered to be Intra_DC. iAboveIntraDir = pcCUAbove ? ( pcCUAbove->isIntra( AbovePartIdx ) ? pcCUAbove->getIntraDir( chType, AbovePartIdx ) : DC_IDX ) : DC_IDX; if (isChroma(chType)) { if (iLeftIntraDir == DM_CHROMA_IDX) { iLeftIntraDir = pcCULeft-> getIntraDir( CHANNEL_TYPE_LUMA, LeftPartIdx ); } if (iAboveIntraDir == DM_CHROMA_IDX) { iAboveIntraDir = pcCUAbove->getIntraDir( CHANNEL_TYPE_LUMA, AbovePartIdx ); } } assert (2<NUM_MOST_PROBABLE_MODES); if(iLeftIntraDir == iAboveIntraDir) // 若左边和上边PU的模式相同,MPM数量为1。 { if( piMode ) { *piMode = 1; } if (iLeftIntraDir > 1) // angular modes { uiIntraDirPred[0] = iLeftIntraDir; uiIntraDirPred[1] = ((iLeftIntraDir + 29) % 32) + 2; uiIntraDirPred[2] = ((iLeftIntraDir - 1 ) % 32) + 2; } else //non-angular { uiIntraDirPred[0] = PLANAR_IDX; uiIntraDirPred[1] = DC_IDX; uiIntraDirPred[2] = VER_IDX; } } else // 若左边和上边PU的模式不同,MPM数量为2。 { if( piMode ) { *piMode = 2; } uiIntraDirPred[0] = iLeftIntraDir; // 左边PU的模式作为MPM模式 uiIntraDirPred[1] = iAboveIntraDir; // 上边PU的模式作为MPM模式 if (iLeftIntraDir && iAboveIntraDir ) //both modes are non-planar { uiIntraDirPred[2] = PLANAR_IDX; } else { uiIntraDirPred[2] = (iLeftIntraDir+iAboveIntraDir)<2? VER_IDX : DC_IDX; } } for (UInt i=0; i<NUM_MOST_PROBABLE_MODES; i++) { assert(uiIntraDirPred[i] < 35); }}
上面的代码中条件if (isChroma(chType))均不会满足,调用时给的chType均是COMPONENT_Y。
0 0
- HM代码阅读:帧内预测(一)
- HM编码器代码阅读(34)——帧内预测(一)
- HM编码器代码阅读(38)——帧内预测(五)帧内预测之正式的预测操作
- HM编码器代码阅读(35)——帧内预测(二)帧内预测总流程
- HM编码器代码阅读(39)——帧内预测(六)帧内预测之色度色度的操作
- HM编码器代码阅读(36)——帧内预测(三)帧内预测之参考像素块的预处理和滤波
- HM编码器代码阅读(37)——帧内预测(四)帧内预测之候选模式列表的建立
- HM编码器代码阅读(40)——帧内预测的总结
- HEVC参考软件(HM)代码阅读之帧内预测:Void TComPrediction::xPredIntraAng
- HM编码器代码阅读(13)——帧间预测之AMVP模式(一)总体流程
- HM编码器代码阅读(16)——帧间预测之AMVP模式(四)预测MV的获取
- HM编码器代码阅读(17)——帧间预测之merge模式(一)Merge模式的介绍以及相关函数
- 关于HEVC HM中的xPredIntraAng帧内预测的方向性预测代码说明
- homerHEVC代码阅读(41)——帧内预测
- HM编码器代码阅读(14)——帧间预测之AMVP模式(二)predInterSearch函数
- HM编码器代码阅读(15)——帧间预测之AMVP模式(三)xGetBlkBits函数
- HM编码器代码阅读(30)——帧间预测之AMVP模式(五)运动估计
- HM编码器代码阅读(31)——帧间预测之AMVP/Merge模式(六)运动补偿
- Java流程控制的陷阱——for循环和foreach循环的陷阱
- 浅谈React的createFactory()方法
- window平台下搭建kafka
- js基本知识比较系列一:获取元素
- 201612-3 权限查询
- HM代码阅读:帧内预测(一)
- SpringMVC集成shiro权限(附源码)
- 给csdn童鞋们的一封信 (csdn为什么不能粘贴图片写博客?)
- Mysql忘记root密码
- HDU 1083 Courses 匈牙利算法二分匹配(邻接矩阵存关系)
- 【编程题目】Pq.10--合并两个排序链表
- 类的加载、连接与初始化
- linux 日志常用查看技巧
- volley源码解析(一)--volley的使用和架构