函数关系
- 说明:
可以看到完成帧内预测编码的核心函数就是 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 种模式;
- 源码:略