openh264解码h264视频帧主流程

一 解析一帧的入口

int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) {

// 解码slice

PDqLayer pCurDqLayer = pCtx->pCurDqLayer;

PFmo pFmo = pCtx->pFmo;

int32_t iRet;

int32_t iNextMbXyIndex, iSliceIdc;

PSlice pSlice = &pCurDqLayer->sLayerInfo.sSliceInLayer;

PSliceHeaderExt pSliceHeaderExt = &pSlice->sSliceHeaderExt;

PSliceHeader pSliceHeader = &pSliceHeaderExt->sSliceHeader;

int32_t iMbX, iMbY;

const int32_t kiCountNumMb = pSliceHeader->pSps->uiTotalMbCount; //need to be correct when fmo or multi slice

uint32_t uiEosFlag = 0;

PWelsDecMbFunc pDecMbFunc;

pSlice->iTotalMbInCurSlice = 0; //initialize at the starting of slice decoding.

if (pCtx->pPps->bEntropyCodingModeFlag) { //cabac 熵编码

if (pSlice->sSliceHeaderExt.bAdaptiveMotionPredFlag ||

pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag ||

pSlice->sSliceHeaderExt.bAdaptiveResidualPredFlag) {

WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,

"WelsDecodeSlice()::::ILP flag exist, not supported with CABAC enabled!");

pCtx->iErrorCode |= dsBitstreamError;

return dsBitstreamError;

}

if (P_SLICE == pSliceHeader->eSliceType) //P Slice帧解析

pDecMbFunc = WelsDecodeMbCabacPSlice;

else if (B_SLICE == pSliceHeader->eSliceType) // B slice解析

pDecMbFunc = WelsDecodeMbCabacBSlice;

else //I_SLICE. B_SLICE is being supported

pDecMbFunc = WelsDecodeMbCabacISlice; // I Slice解析

} else { //

if (P_SLICE == pSliceHeader->eSliceType) {

pDecMbFunc = WelsDecodeMbCavlcPSlice;

} else if (B_SLICE == pSliceHeader->eSliceType) {

pDecMbFunc = WelsDecodeMbCavlcBSlice;

} else { //I_SLICE

pDecMbFunc = WelsDecodeMbCavlcISlice;

}

}

二 解析P slice函数

int32_t WelsDecodeMbCabacPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {

PDqLayer pCurDqLayer = pCtx->pCurDqLayer; //当前解码上下文

PSlice pSlice = &pCurDqLayer->sLayerInfo.sSliceInLayer; // slice上下文

PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; // slice header

PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0]; //参考帧上下文

uint32_t uiCode;

int32_t iMbXy = pCurDqLayer->iMbXyIndex;

int32_t i;

SWelsNeighAvail uiNeighAvail;

pCurDqLayer->pCbp[iMbXy] = 0; //code block parttern信息

pCurDqLayer->pCbfDc[iMbXy] = 0;

pCurDqLayer->pChromaPredMode[iMbXy] = C_PRED_DC;

pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] = true;

pCurDqLayer->pTransformSize8x8Flag[iMbXy] = false;

GetNeighborAvailMbType (&uiNeighAvail, pCurDqLayer); //填充邻居mb_type 为当前宏块解码做准备

WELS_READ_VERIFY (ParseSkipFlagCabac (pCtx, &uiNeighAvail, uiCode)); //解析是否为skip块

if (uiCode) {

int16_t pMv[2] = {0};

pCurDqLayer->pDec->pMbType[iMbXy] = MB_TYPE_SKIP;

ST32 (&pCurDqLayer->pNzc[iMbXy][0], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][4], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][8], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][12], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][16], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][20], 0);

pCurDqLayer->pInterPredictionDoneFlag[iMbXy] = 0;

memset (pCurDqLayer->pDec->pRefIndex[0][iMbXy], 0, sizeof (int8_t) * 16);

bool bIsPending = GetThreadCount (pCtx) > 1;

pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[0] && (ppRefPic[0]->bIsComplete

|| bIsPending));

//predict mv

PredPSkipMvFromNeighbor (pCurDqLayer, pMv); //通过周围块的信息,计算得到当前块的mvp

for (i = 0; i < 16; i++) {

ST32 (pCurDqLayer->pDec->pMv[0][iMbXy][i], * (uint32_t*)pMv);

ST32 (pCurDqLayer->pMvd[0][iMbXy][i], 0);

}

//if (!pSlice->sSliceHeaderExt.bDefaultResidualPredFlag) {

// memset (pCurDqLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (int16_t));

//}

//reset rS

pCurDqLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp; //??????????????? dqaunt of previous mb 前一个qp,当前

//解码得到 delta + 这里的qp就是实际qp

for (i = 0; i < 2; i++) {

pCurDqLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurDqLayer->pLumaQp[iMbXy] +

pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];

//计算得到chromaqp,和lumaqp有对应关系

}

//for neighboring CABAC usage

pSlice->iLastDeltaQp = 0;

WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));

return ERR_NONE;

}

WELS_READ_VERIFY (WelsDecodeMbCabacPSliceBaseMode0 (pCtx, &uiNeighAvail, uiEosFlag)); //实际解析slice 中MB列表

return ERR_NONE;

三 解析Bslice过程

int32_t WelsDecodeMbCabacBSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {

//解析B slice

PDqLayer pCurDqLayer = pCtx->pCurDqLayer; //当前帧上下文

PSlice pSlice = &pCurDqLayer->sLayerInfo.sSliceInLayer; //Slice指针

PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; //当前slice头指着

PPicture* ppRefPicL0 = pCtx->sRefPic.pRefList[LIST_0]; //前向参考列表

PPicture* ppRefPicL1 = pCtx->sRefPic.pRefList[LIST_1]; //后向参考列表

uint32_t uiCode; //

int32_t iMbXy = pCurDqLayer->iMbXyIndex;

int32_t i;

SWelsNeighAvail uiNeighAvail;

pCurDqLayer->pCbp[iMbXy] = 0; //

pCurDqLayer->pCbfDc[iMbXy] = 0;

pCurDqLayer->pChromaPredMode[iMbXy] = C_PRED_DC;

pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] = true;

pCurDqLayer->pTransformSize8x8Flag[iMbXy] = false;

GetNeighborAvailMbType (&uiNeighAvail, pCurDqLayer); //填充周围宏块信息

WELS_READ_VERIFY (ParseSkipFlagCabac (pCtx, &uiNeighAvail, uiCode)); //解析 skip标记

memset (pCurDqLayer->pDirect[iMbXy], 0, sizeof (int8_t) * 16);

bool bIsPending = GetThreadCount (pCtx) > 1;

if (uiCode) {

int16_t pMv[LIST_A][2] = { {0, 0}, { 0, 0 } };

int8_t ref[LIST_A] = { 0 };

pCurDqLayer->pDec->pMbType[iMbXy] = MB_TYPE_SKIP | MB_TYPE_DIRECT;

ST32 (&pCurDqLayer->pNzc[iMbXy][0], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][4], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][8], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][12], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][16], 0);

ST32 (&pCurDqLayer->pNzc[iMbXy][20], 0);

pCurDqLayer->pInterPredictionDoneFlag[iMbXy] = 0;

memset (pCurDqLayer->pDec->pRefIndex[LIST_0][iMbXy], 0, sizeof (int8_t) * 16);

memset (pCurDqLayer->pDec->pRefIndex[LIST_1][iMbXy], 0, sizeof (int8_t) * 16);

pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPicL0[0] && (ppRefPicL0[0]->bIsComplete

|| bIsPending)) || ! (ppRefPicL1[0] && (ppRefPicL1[0]->bIsComplete || bIsPending));

if (pCtx->bMbRefConcealed) {

SLogContext* pLogCtx = & (pCtx->sLogCtx);

WelsLog (pLogCtx, WELS_LOG_ERROR, "Ref Picture for B-Slice is lost, B-Slice decoding cannot be continued!");

return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_DATA, ERR_INFO_REFERENCE_PIC_LOST);

}

SubMbType subMbType;

if (pSliceHeader->iDirectSpatialMvPredFlag) { //Direct 块类型判断

//predict direct spatial mv

int32_t ret = PredMvBDirectSpatial (pCtx, pMv, ref, subMbType);

if (ret != ERR_NONE) {

return ret;

}

} else {

//temporal direct mode

int32_t ret = PredBDirectTemporal (pCtx, pMv, ref, subMbType);

if (ret != ERR_NONE) {

return ret;

}

}

//reset rS

pCurDqLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp; //??????????????? dqaunt of previous mb

for (i = 0; i < 2; i++) {

pCurDqLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurDqLayer->pLumaQp[iMbXy] +

pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];

}

//for neighboring CABAC usage

pSlice->iLastDeltaQp = 0;

WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));

return ERR_NONE;

}

WELS_READ_VERIFY (WelsDecodeMbCabacBSliceBaseMode0 (pCtx, &uiNeighAvail, uiEosFlag)); //实际解析BSlice中的mb

return ERR_NONE;

}

四 解析ISlice过程

int32_t WelsDecodeMbCabacISliceBaseMode0 (PWelsDecoderContext pCtx, uint32_t& uiEosFlag) {

//解析I slice

PDqLayer pCurDqLayer = pCtx->pCurDqLayer; //当前帧解码上下文

PBitStringAux pBsAux = pCurDqLayer->pBitStringAux;

PSlice pSlice = &pCurDqLayer->sLayerInfo.sSliceInLayer; //slice上下文

PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;

SWelsNeighAvail sNeighAvail;

int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;

int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;

int32_t iMbXy = pCurDqLayer->iMbXyIndex;

int32_t i;

uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;

ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);

pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] = true;

pCurDqLayer->pTransformSize8x8Flag[iMbXy] = false;

pCurDqLayer->pInterPredictionDoneFlag[iMbXy] = 0;

pCurDqLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;

GetNeighborAvailMbType (&sNeighAvail, pCurDqLayer);

WELS_READ_VERIFY (ParseMBTypeISliceCabac (pCtx, &sNeighAvail, uiMbType)); //解析mb类型

if (uiMbType > 25) { //非法的mb类型

return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_MB_TYPE);

} else if (!pCtx->pSps->uiChromaFormatIdc && ((uiMbType >= 5 && uiMbType <= 12) || (uiMbType >= 17

&& uiMbType <= 24))) { //如果没有色度信息,这里mb类型不合法的类型判断

return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_MB_TYPE);

} else if (25 == uiMbType) { //I_PCM

WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "I_PCM mode exists in I slice!");

WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx)); //解析PCM 信息,cabac

pSlice->iLastDeltaQp = 0;

WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));

if (uiEosFlag) {

RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);

}

return ERR_NONE;

} else if (0 == uiMbType) { //I4x4 16个4x4的帧内块

ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);

pCurDqLayer->pDec->pMbType[iMbXy] = MB_TYPE_INTRA4x4;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值