openh264 帧间预测编码原理:WelsMdP16x16函数

openh264 帧间预测编码

  • 帧间预测编码是视频压缩技术中的关键方法之一,它主要用于减少视频序列中时间维度上的冗余。这种编码方式依赖于视频帧之间的空间相关性,通过预测和补偿来减少数据量,从而实现高效的视频压缩。帧间预测编码广泛应用于各种视频编码标准,包括H.264/AVC、H.265/HEVC、VP9和AV1等。通过减少时间冗余,帧间预测编码显著提高了视频数据的压缩率,同时保持了视频质量。
  • 关于 openh264 帧间预测编码整体过程可以参考:openh264 帧间预测编码过程源码分析

WelsMdP16x16函数介绍

  1. 功能:实现了对16x16宏块的运动估计(Motion Estimation, ME)和运动补偿(Motion Compensation, MC),并得到 P16x16 块的代价 cost;
  2. 参数
  • pFunc: SWelsFuncPtrList* 类型的指针,指向一个函数指针列表,包含编码过程中使用的各种函数。
  • pCurLayer: SDqLayer* 类型的指针,指向当前处理的解码队列层(Decoding Queue Layer),包含当前宏块的编码和解码信息。
  • pWelsMd: SWelsMD* 类型的指针,指向运动检测(Motion Detection)相关的上下文信息,包括运动估计和补偿的数据结构。
  • pSlice: SSlice* 类型的指针,指向当前处理的切片(Slice)信息,切片是视频帧中的一个逻辑分段,包含一系列的宏块。
  • pCurMb: SMB* 类型的指针,指向当前正在处理的宏块。
  1. 返回值:SWelsME* pMe16x16中代价uiSatdCost;
  2. 函数关系图
    在这里插入图片描述

WelsMdP16x16函数原理

  • 通过 pMbCache = &pSlice->sMbCacheInfo; 获取当前切片的宏块缓存信息;
  • pMe16x16 指向用于16x16块运动估计的结构体,它被初始化为 pWelsMd->sMe.sMe16x16;
  • uiNeighborAvail 存储了当前宏块邻居(左侧、顶部)的存在性信息;
  • kiMbWidth 和 kiMbHeight 分别获取编码图像的宏块宽度和高度;
  • InitMe 函数用于初始化运动估计过程,包括编码宏块、参考宏块、屏幕块特征存储等信息;
  • pMe16x16->uSadPredISatd.uiSadPred 设置为 pWelsMd->iSadPredMb,这是预测的SAD值;
  • MV候选列表初始化:
    • pSlice->uiMvcNum 重置为0,表示MV候选列表的开始;
    • pMe16x16->sMvBase 作为基础MV添加到候选列表;
  • 空间MV预测:
    • 如果当前宏块的左侧或上方有邻居宏块,它们各自的16x16 MV被添加到候选列表。
  • 时间MV预测:
    • 如果参考帧是P切片,并且当前宏块在图像的右侧或下方有宏块,这些宏块的MV也被添加到候选列表,并根据 pSlice->sScaleShift 进行缩放。
  • MV预测:
    • PredMv 函数用于根据MV候选列表预测当前宏块的MV。
  • 执行运动搜索:
    • pFunc->pfMotionSearch[0] 调用指定的运动搜索算法来找到最佳MV,指向WelsMotionEstimateSearch函数完成运动估计搜索过程;
  • 更新宏块MV:
    • pCurMb->sP16x16Mv 和解码图像的MV列表 pCurLayer->pDecPic->sMvList 被更新为找到的最佳MV。
  • 返回SATD成本:
    • 函数返回 pMe16x16->uiSatdCost,这是与最佳MV相关的SATD(Sum of Absolute Transformed Differences)成本。

WelsMdP16x16函数源码

int32_t WelsMdP16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb) {
  SMbCache* pMbCache = &pSlice->sMbCacheInfo;
  SWelsME* pMe16x16 = &pWelsMd->sMe.sMe16x16;
  uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
  const int32_t kiMbWidth  = pCurLayer->iMbWidth;  // for assign once
  const int32_t kiMbHeight = pCurLayer->iMbHeight;
  InitMe (*pWelsMd, BLOCK_16x16, pMbCache->SPicData.pEncMb[0], pMbCache->SPicData.pRefMb[0],
          pCurLayer->pRefPic->pScreenBlockFeatureStorage,
          *pMe16x16);
  //not putting the line below into InitMe to avoid judging mode in InitMe
  pMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;

  pSlice->uiMvcNum = 0;
  pSlice->sMvc[pSlice->uiMvcNum++] = pMe16x16->sMvBase;
  //spatial motion vector predictors
  if (uiNeighborAvail & LEFT_MB_POS) { //left available
    pSlice->sMvc[pSlice->uiMvcNum++] = (pCurMb - 1)->sP16x16Mv;
  }
  if (uiNeighborAvail & TOP_MB_POS) { //top available
    pSlice->sMvc[pSlice->uiMvcNum++] = (pCurMb - kiMbWidth)->sP16x16Mv;
  }
  //temporal motion vector predictors
  if (pCurLayer->pRefPic->iPictureType == P_SLICE) {
    if (pCurMb->iMbX < kiMbWidth - 1) {
      SMVUnitXY sTempMv = pCurLayer->pRefPic->sMvList[pCurMb->iMbXY + 1];
      pSlice->sMvc[pSlice->uiMvcNum].iMvX = sTempMv.iMvX >> pSlice->sScaleShift;
      pSlice->sMvc[pSlice->uiMvcNum].iMvY = sTempMv.iMvY >> pSlice->sScaleShift;
      ++ pSlice->uiMvcNum;
    }
    if (pCurMb->iMbY < kiMbHeight - 1) {
      SMVUnitXY sTempMv = pCurLayer->pRefPic->sMvList[pCurMb->iMbXY + kiMbWidth];
      pSlice->sMvc[pSlice->uiMvcNum].iMvX = sTempMv.iMvX >> pSlice->sScaleShift;
      pSlice->sMvc[pSlice->uiMvcNum].iMvY = sTempMv.iMvY >> pSlice->sScaleShift;
      ++ pSlice->uiMvcNum;
    }
  }

  PredMv (&pMbCache->sMvComponents, 0, 4, 0, & (pMe16x16->sMvp));
  pFunc->pfMotionSearch[0] (pFunc, pCurLayer, pMe16x16, pSlice);

  pCurMb->sP16x16Mv = pMe16x16->sMv;
  pCurLayer->pDecPic->sMvList[pCurMb->iMbXY] = pMe16x16->sMv;

  return pMe16x16->uiSatdCost;
}
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Codec Conductor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值