函数关系
说明: 可以看到完成帧内预测编码的核心函数就是 WelsMdI16x16
、WelsMdI4x4
、WelsMdI4x4Fast
、WelsMdIntraChroma
四个函数。
原理
WelsMdI16x16函数
功能 :针对16x16像素块的帧内模式决策过程 :
局部变量申明; 根据宏块的领域宏块情况计算得出iOffset; iAvailCount 和 kpAvailMode 用于获取当前宏块可用的帧内预测模式数量和预测模式列表; 如果iAvailCount大于 3,且提供 pfIntra16x16Combined3函数;
则调用pfIntra16x16Combined3
函数来获取最佳模式iBestMode和成本iBestCost; 从kpAvailMode[3]中确定当前模式iCurMode,表明考虑 第四种模式; 调用pfGetLumaI16x16Pred
函数,根据当前模式编号 iCurMode 生成预测块,并将结果存储在 pDst 中; pfMdCost[BLOCK_16x16]
函数计算当前预测块 pDst 和编码图像 pEnc 之间的成本iCurCost;iCurCost小于iBestCost,
将iCurMode和iCurCost确定最佳模式iBestMode和成本iBestCost; 否则,
则调用pfGetLumaI16x16Pred
函数使用最佳模式iBestMode重新生成预测块,并存储在 pDst 中; iIdx 被设置为1,最佳成本 iBestCost 被加上量化参数 iLambda,作为总开销; 否则
iBestMode 被初始化为第一个可用模式,即 kpAvailMode[0]; for 循环遍历所有可用的模式iAvailCount;
在每次循环迭代中,iCurMode 被设置为当前考虑的模式编号iCurMode; 调用 pfGetLumaI16x16Pred[iCurMode]
函数,根据当前模式编号 iCurMode 生成预测块; 使用 pfMdCost[BLOCK_16x16]
函数计算当前预测块 pDst 和编码图像 pEnc 之间的成本iCurCost; iCurCost 加上量化参数 iLambda 与当前模式编号的编码长度(使用 BsSizeUE
函数和 g_kiMapModeI16x16 数组计算)的乘积; 如果 iCurCost小于 iBestCost;
更新iBestMode、iBestCost、iIdx、pDst;iIdx 通过异或操作 ^ 0x01 来切换,这在每次找到更好的模式时都会发生; iIdx用来指向预测块pPredI16x16; 更新缓存SMbCache中pMemPredChroma、pMemPredLuma、uiLumaI16x16Mode; 返回 最佳代价iBestCost。
原理图 : 说明 :
pfGetLumaI16x16Pred
函数指针根据不同的模式指向不同的函数,具体在WelsInitIntraPredFuncs
函数中定义。pfMdCost函数指针根据 fastmode 模式指向pfSampleSad
或pfSampleSatd
函数指针,而且根据不同预测模式指向不同的函数实现,具体在WelsInitSampleSadFunc
函数中定义。
源码:
int32_t WelsMdI16x16 ( SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SMbCache* pMbCache, int32_t iLambda) {
const int8_t * kpAvailMode;
int32_t iAvailCount;
int32_t iIdx = 0 ;
uint8_t * pPredI16x16[ 2 ] = { pMbCache-> pMemPredMb, pMbCache-> pMemPredMb + 256 } ;
uint8_t * pDst = pPredI16x16[ 0 ] ;
uint8_t * pDec = pMbCache-> SPicData. pCsMb[ 0 ] ;
uint8_t * pEnc = pMbCache-> SPicData. pEncMb[ 0 ] ;
int32_t iLineSizeDec = pCurDqLayer-> iCsStride[ 0 ] ;
int32_t iLineSizeEnc = pCurDqLayer-> iEncStride[ 0 ] ;
int32_t i, iCurCost, iCurMode, iBestMode, iBestCost = INT_MAX;
int32_t iOffset = pMbCache-> uiNeighborIntra & 0x07 ;
iAvailCount = g_kiIntra16AvaliMode[ iOffset] [ 4 ] ;
kpAvailMode = g_kiIntra16AvaliMode[ iOffset] ;
if ( iAvailCount > 3 && pFunc-> sSampleDealingFuncs. pfIntra16x16Combined3) {
iBestCost = pFunc-> sSampleDealingFuncs. pfIntra16x16Combined3 ( pDec, iLineSizeDec, pEnc, iLineSizeEnc, & iBestMode,
iLambda, pDst) ;
iCurMode = kpAvailMode[ 3 ] ;
pFunc-> pfGetLumaI16x16Pred[ iCurMode] ( pDst, pDec, iLineSizeDec) ;
iCurCost = pFunc-> sSampleDealingFuncs. pfMdCost[ BLOCK_16x16] ( pDst, 16 , pEnc, iLineSizeEnc) + iLambda * 4 ;
if ( iCurCost < iBestCost) {
iBestMode = iCurMode;
iBestCost = iCurCost;
} else {
pFunc-> pfGetLumaI16x16Pred[ iBestMode] ( pDst, pDec, iLineSizeDec) ;
}
iIdx = 1 ;
iBestCost += iLambda;
} else {
iBestMode = kpAvailMode[ 0 ] ;
for ( i = 0 ; i < iAvailCount; ++ i) {
iCurMode = kpAvailMode[ i] ;
assert ( iCurMode >= 0 && iCurMode < 7 ) ;
pFunc-> pfGetLumaI16x16Pred[ iCurMode] ( pDst, pDec, iLineSizeDec) ;
iCurCost = pFunc-> sSampleDealingFuncs. pfMdCost[ BLOCK_16x16] ( pDst, 16 , pEnc, iLineSizeEnc) ;
iCurCost += iLambda * ( BsSizeUE ( g_kiMapModeI16x16[ iCurMode] ) ) ;
if ( iCurCost < iBestCost) {
iBestMode = iCurMode;
iBestCost = iCurCost;
iIdx = iIdx ^ 0x01 ;
pDst = pPredI16x16[ iIdx] ;
}
}
}
pMbCache-> pMemPredChroma = pPredI16x16[ iIdx] ;
pMbCache-> pMemPredLuma = pPredI16x16[ iIdx ^ 0x01 ] ;
pMbCache-> uiLumaI16x16Mode = iBestMode;
return iBestCost;
}
WelsMdI4x4函数
功能 :针对4x4像素块的帧内模式决策过程 :类似 I16x16,只不过预测模式更多,有 16 种模式;源码 :略
WelsMdI4x4Fast函数
功能 :针对4x4像素块的帧内模式决策的快速实现逻辑过程 :类似 I16x16,只不过预测模式更多,有 16 中模式,但采用了快速算法;源码 :略
WelsMdIntraChroma函数
功能 :针对色度像素块的帧内模式决策过程 :类似 I16x16决策过程,色度的预测模式跟 I16x16 块一样,有 7 种模式;源码 :略