当前位置: 首页 > news >正文

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;

http://www.lryc.cn/news/4842.html

相关文章:

  • 【个人笔记】C语言位域
  • ROS笔记(1)——ROS的核心概念
  • 动态SQL使用【JavaEE】
  • leetcode刷题
  • 移动设备安全管理基础指南
  • 【Java|多线程与高并发】 使用Thread 类创建线程的5种方法如何查看程序中的线程
  • 零基础学MySQL(五)-- 详细讲解数据库中的常用函数
  • 第4章 流程控制-if-else,Switch,For循环(循环守卫,循环步长,倒叙打印),While循环,多重循环...
  • 2.4G-WiFi连接路由器过程
  • 3. SpringMVC Rest 风格
  • Python3简介
  • 如何学习PMP?
  • 【DSP视频教程】第11期:插补算法,曲线拟合丝滑顺畅,统计函数和基础函数加速实现,汇集SIMD,饱和和MAC乘累加应用实战(2023-02-12)
  • 分类模型评估:混淆矩阵、准确率、召回率、ROC
  • 算法 ——世界 一
  • 2023年3月AMA-CDGA/CDGP数据治理认证考试这些城市可以报名
  • Java变量和数据类型,超详细整理,适合新手入门
  • Echarts 设置折线图拐点的颜色,边框等样式,hover时改变颜色
  • 做 SQL 性能优化真是让人干瞪眼
  • SpringBoot(3)之包结构
  • test2
  • LoadRunner安装教程
  • VHDL语言基础-Testbech
  • 机器学习基础总结
  • linux的三权分立设计思路和用户创建(安全管理员、系统管理员和审计管理员)
  • revit中如何创建有坡度的排水沟及基坑?
  • Web自动化测试——selenium篇(一)
  • 认识 CSS pointer-events 属性
  • 【java】springboot和springcloud区别
  • ​网易游戏实时 HTAP 计费风控平台建设