HM编码器代码阅读(37)——帧内预测(四)帧内预测之候选模式列表的建立
来源:互联网 发布:360软件强力卸载 编辑:程序博客网 时间:2024/04/30 22:03
候选模式列表的建立
注意:如果没有特别说明,操作的对象都是亮度块(Luma)
帧内预测也可以分成两种方式,一种是常规方式,另一种是快速方式
在常规方式
所有的35种帧内预测模式都被添加到候选模式列表中,在后续的惭怍中,对每一个模式都进行预测、变换、量化等操作,速度很慢。
相关代码在estIntraPredQT函数中
UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ];//8Bool doFastSearch = (numModesForFullRD != numModesAvailable);//true// 使用快速模式if (doFastSearch){// 省略快速模式的实现代码}// 使用常规方式else{for( Int i=0; i < numModesForFullRD; i++){uiRdModeList[i] = i;}}
在快速方式
先遍历35种帧内预测模式,对于每一种模式都进行预测操作,选出代价最优的几种模式作为候选模式,添加到候选模式列表中。
同时,因为相邻的PU通常具有很强的相关性,因此,可以使用相邻PU的帧内模式来预测当前PU的帧内模式。预测之后可以得到若干个模式,把这些模式加入模式候选列表中。
在后续的操作中,只对这几种模式进行预测、变换、量化等操作,因为候选列表中的模式的数量比较少,因此速度会很快。
相关代码在estIntraPredQT函数中
UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ];//8Bool doFastSearch = (numModesForFullRD != numModesAvailable);//true// 使用快速模式if (doFastSearch){assert(numModesForFullRD < numModesAvailable);for( Int i=0; i < numModesForFullRD; i++ ) {// 用于存储每一种模式的消耗CandCostList[ i ] = MAX_DOUBLE;}CandNum = 0;// 遍历35种帧内预测模式,选取若干个代价比较小的模式作为后续处理的模式for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) // 总共有35种模式,numModesAvailable = 35{UInt uiMode = modeIdx;// 对亮度块进行预测predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );// use hadamard transform here// 使用hadamard变换,计算SATD的值UInt uiSad = m_pcRdCost->calcHAD(g_bitDepthY, piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );UInt iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );// 计算此种模式的代价Double cost = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();// 更新候选列表CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );}#if FAST_UDI_USE_MPMInt uiPreds[3] = {-1, -1, -1};Int iMode = -1;// 根据相邻块的预测模式来对当前块的模式进行预测,得到若干模式(称为预测模式),存放在uiPreds中Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode );if( iMode >= 0 ){// 将候选列表的索引设置为此模式numCand = iMode;}// 遍历预测的模式,如果它不在模式候选列表中,那么把它添加到模式候选列表中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;}}#endif // FAST_UDI_USE_MPM}// 使用常规方式else{for( Int i=0; i < numModesForFullRD; i++){uiRdModeList[i] = i;}}
从所有的35种模式中选出若干最优模式
// 遍历35种帧内预测模式,选取若干个代价比较小的模式作为后续处理的模式for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) // 总共有35种模式,numModesAvailable = 35{UInt uiMode = modeIdx;// 对亮度块进行预测predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );// use hadamard transform here// 使用hadamard变换,计算SATD的值UInt uiSad = m_pcRdCost->calcHAD(g_bitDepthY, piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );UInt iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );// 计算此种模式的代价Double cost = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();// 更新候选列表CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );}
亮度块的帧内预测函数
// 亮度块的帧内预测Void TComPrediction::predIntraLumaAng(TComPattern* pcTComPattern, UInt uiDirMode, Pel* piPred, UInt uiStride, Int iWidth, Int iHeight, Bool bAbove, Bool bLeft ){Pel *pDst = piPred;Int *ptrSrc;assert( g_aucConvertToBit[ iWidth ] >= 0 ); // 4x 4assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128assert( iWidth == iHeight );// 获取数据的指针ptrSrc = pcTComPattern->getPredictorPtr( uiDirMode, g_aucConvertToBit[ iWidth ] + 2, m_piYuvExt );// get starting pixel in block// 获取块中的开始像素Int sw = 2 * iWidth + 1; // 9// Create the prediction// 如果指定了planar模式if ( uiDirMode == PLANAR_IDX ){// planar预测模式xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight );}else{// 没有指定planar模式// 区分水平或者垂直模式进行预测if ( (iWidth > 16) || (iHeight > 16) ){xPredIntraAng(g_bitDepthY, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, uiDirMode, bAbove, bLeft, false );}else{xPredIntraAng(g_bitDepthY, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, uiDirMode, bAbove, bLeft, true );// 观察是否为DC模式if( (uiDirMode == DC_IDX ) && bAbove && bLeft ){// 对DC模式进行滤波xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight);}}}}
模式的预测
因为相邻的PU通常具有很强的相关性,因此,可以使用相邻PU的帧内模式来预测当前PU的帧内模式。预测之后可以得到若干个模式,把这些模式加入模式候选列表中。
相关代码在estIntraPredQT函数中
Int uiPreds[3] = {-1, -1, -1};Int iMode = -1;// 根据相邻块的预测模式来对当前块的模式进行预测,得到若干模式(称为预测模式),存放在uiPreds中Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode );if( iMode >= 0 ){// 将候选列表的索引设置为此模式numCand = iMode;}// 遍历预测的模式,如果它不在模式候选列表中,那么把它添加到模式候选列表中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;}}
模式预测函数
预测的步骤如下:
1、假设当前块的左边是A,上面的是B,candList数组用于存放预测的模式
2、如果modeA==modeB
(1)modeA和modeB都是planar或者DC模式,那么candList[0] =planar,candList[1]=DC,candList[2]=26
(2)modeA和modeB都是角度模式,那么,candList[0]=modeA,candList[1]和candList[2]等于modeA相邻的两个模式
3、如果modeA!=modeB,那么candList[0]=modeA,candList[1]=modeB,candList[2]则要分几种情况
(1)modeA和modeB都不是planar模式,那么candList[2]=planar
(2)当(1)不满足,而且modeA和modeB都不是DC模式,那么candList[2]=DC
(3)当(1)和(2)不满足,candList[2]=26
Int TComDataCU::getIntraDirLumaPredictor( UInt uiAbsPartIdx, Int* uiIntraDirPred, Int* piMode ){TComDataCU* pcTempCU;UInt uiTempPartIdx;Int iLeftIntraDir, iAboveIntraDir;Int uiPredNum = 0;// Get intra direction of left PUpcTempCU = getPULeft( uiTempPartIdx, m_uiAbsIdxInLCU + uiAbsPartIdx );iLeftIntraDir = pcTempCU ? ( pcTempCU->isIntra( uiTempPartIdx ) ? pcTempCU->getLumaIntraDir( uiTempPartIdx ) : DC_IDX ) : DC_IDX;// Get intra direction of above PUpcTempCU = getPUAbove( uiTempPartIdx, m_uiAbsIdxInLCU + uiAbsPartIdx, true, true );iAboveIntraDir = pcTempCU ? ( pcTempCU->isIntra( uiTempPartIdx ) ? pcTempCU->getLumaIntraDir( uiTempPartIdx ) : DC_IDX ) : DC_IDX;uiPredNum = 3;if(iLeftIntraDir == iAboveIntraDir){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{if( piMode ){*piMode = 2;}uiIntraDirPred[0] = iLeftIntraDir;uiIntraDirPred[1] = iAboveIntraDir;if (iLeftIntraDir && iAboveIntraDir ) //both modes are non-planar{uiIntraDirPred[2] = PLANAR_IDX;}else{uiIntraDirPred[2] = (iLeftIntraDir+iAboveIntraDir)<2? VER_IDX : DC_IDX;}}return uiPredNum;}
- HM编码器代码阅读(37)——帧内预测(四)帧内预测之候选模式列表的建立
- HM编码器代码阅读(38)——帧内预测(五)帧内预测之正式的预测操作
- HM编码器代码阅读(39)——帧内预测(六)帧内预测之色度色度的操作
- HM编码器代码阅读(16)——帧间预测之AMVP模式(四)预测MV的获取
- HM编码器代码阅读(36)——帧内预测(三)帧内预测之参考像素块的预处理和滤波
- HM编码器代码阅读(35)——帧内预测(二)帧内预测总流程
- HM编码器代码阅读(40)——帧内预测的总结
- HM编码器代码阅读(34)——帧内预测(一)
- HM编码器代码阅读(13)——帧间预测之AMVP模式(一)总体流程
- HM编码器代码阅读(14)——帧间预测之AMVP模式(二)predInterSearch函数
- HM编码器代码阅读(15)——帧间预测之AMVP模式(三)xGetBlkBits函数
- HM编码器代码阅读(30)——帧间预测之AMVP模式(五)运动估计
- HM编码器代码阅读(31)——帧间预测之AMVP/Merge模式(六)运动补偿
- HM代码阅读:帧内预测(一)
- HM编码器代码阅读(17)——帧间预测之merge模式(一)Merge模式的介绍以及相关函数
- HM编码器代码阅读(33)——帧间预测的总结
- HM编码器代码阅读(32)——帧间预测之AMVP/Merge模式(七)encodeResAndCalcRdInterCU函数:残差计算、变换量化
- HEVC参考软件(HM)代码阅读之帧内预测:Void TComPrediction::xPredIntraAng
- hadoop2.5.x完全分布式集群搭建配置
- 设计模式简介
- 简单的<c:forEach>应用
- Keil逻辑分析仪的使用
- Android开发圆形头像,RoundedImageView
- HM编码器代码阅读(37)——帧内预测(四)帧内预测之候选模式列表的建立
- 好友csgo被血虐
- 元件(Component)
- Android Notification的使用
- The number of method references in a .dex file cannot exceed 64K.
- 输入一个链表,从尾到头打印链表每个节点的值。
- ajax小记
- Packagist 镜像使用方法
- animationSet repeatMode无效?