openh264的帧间预测过程分为基本层和增强层,基本层预测在WelsMdInterMb函数中实现,增强层预测在WelsMdInterMbEnhancelayer函数中实现。这两个函数的调用都在WelsMdInterMbLoop函数中通过函数指针来调用。
WelsMdInterMbLoop函数的过程如下:
int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY) {
.....
//这个for循环是遍历一个slice中的所有宏块
for(;;){
iCurMbIdx = iNextMbIdx;//当前宏块索引
pCurMb = &pMbList[ iCurMbIdx ];//当前宏块
//step(1): set QP for the current MB设置当前宏块的QP和目标比特数,与码率相关的变量的初始化
pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
//step (2). save some vale for future use, initial pWelsMd
WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);//获取相邻宏块的帧内的信息
WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);//获取相邻宏块的帧间的运动信息和参考宏块的类型
WelsInitInterMDStruc (pCurMb, pMvdCostTable, kiMvdInterTableStride, pMd);
pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);//帧间预测入口,通过这个指针来调用基本层或增强层的预测过程
//step (4): save from the MD process from future use保存当前宏块的类型,供之后编码帧做参考使用
WelsMdInterSaveSadAndRefMbType ((pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);
.....
//step (5): update cache
UpdateNonZeroCountCache (pCurMb, pMbCache);//保存宏块的非零系数
//step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);//帧间预测熵编码
......
//step (7): reconstruct current MB
pCurMb->uiSliceIdc = kiSliceIdx;
OutputPMbWithoutConstructCsRsNoCopy (pEncCtx, pCurLayer, pSlice, pCurMb);//重构宏块
WelsCountMbType (pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb);//计算每种类型的宏块的数目
iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);//确定下一个宏块
}
}