VTM10.0代码学习10:EncGOP_compressGOP()

此系列是为了记录自己学习VTM10.0的过程,目前正在看编码端。主要的参考文档有JVET-S2001-vH和JVET-S2002-v1。由于本人水平有限,出现的错误恳请大家指正,欢迎与大家一起交流进步。


上一篇博文(VTM10.0代码学习9)提到compressGOP(),这个函数由于涉及到slice的设置,十分地冗长,足足有1700多行。在解码端也有类似的部分,就在本系列的第二篇博文(VTM10.0代码学习2)提到。刚看VTM没多久的我又怎能啃下这块硬骨头,就战略性跳过很多内容了。现在稍微有些底气来说说这块,但我应该写得很烂,大家见谅啊。


1. 初始设置

OutputBitstream  *pcBitstreamRedirect;//将码流装入VCL-NALU之前暂存的地方
pcBitstreamRedirect = new OutputBitstream;

Picture* scaledRefPic[MAX_NUM_REF] = {
   };

xInitGOP( iPOCLast, iNumPicRcvd, isField, isEncodeLtRef );

pcBitstreamRedirect:将码流装入VCL-NALU之前暂存的地方

scaledRefPic:存储着缩放后的参考帧

xInitGOP:设置m_iGopSize,表示当前GOP的大小,除了第一帧是1的情况外,是恒定的即使当前GOP没有读取到足够的帧数


m_pcCfg->setEncodedFlag( iGOPid, false );
auto beforeTime = std::chrono::steady_clock::now();

setEncodedFlag():将m_RPLList0、m_RPLList1、m_GOPList中的m_isEncoded设置为false,表示当前帧还未编码。m_GOPList里面存着一个GOP内每个帧的一些信息(例如POC、I/B/P帧等等),这些都是直接从cfg文件中得到的。m_RPLList0和m_RPLList1相对侧重于存储每个帧有关参考帧列表1和0的信息。

now():记录一下起始时间


int iTimeOffset;//表示当前编码帧是当前GOP播放顺序的第几帧
int pocCurr;//表示当前编码帧的POC

if(iPOCLast == 0)
{
   
    pocCurr=0;
    iTimeOffset = 1;
}
else
{
   
    pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC;
    iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC;
}

if (pocCurr  >= m_pcCfg->getFramesToBeEncoded())
{
   
    continue;
}

iTimeOffset:表示当前编码帧的POC相对于当前GOP播放顺序第一帧的POC的偏移

pocCurr:表示当前编码帧的POC

最后一个if分支:表示如果当前编码帧的POC超出要编码的帧数,跳过之后的步骤(因为我省略了外循环语句,所以看上去有些奇怪)


if( getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_N_LP )
{
   
    m_iLastIDR = pocCurr;//更新编码顺序之前最近IDR帧的POC
}

xGetBuffer( rcListPic, rcListPicYuvRecOut,
           iNumPicRcvd, iTimeOffset, pcPic, pocCurr, isField );//相当于初始化指针pcPic,设置重建帧指针的指向
picHeader = pcPic->cs->picHeader;
picHeader->setSPSId( pcPic->cs->pps->getSPSId() );
picHeader->setPPSId( pcPic->cs->pps->getPPSId() );
picHeader->setSplitConsOverrideFlag(false);
// initial two flags to be false
picHeader->setPicInterSliceAllowedFlag(false);
picHeader->setPicIntraSliceAllowedFlag(false);

if分支:如果当前帧的NALU类型是IDR则更新m_iLastIDR,表示编码顺序之前最近IDR帧的POC。要想知道如何决定帧的NALU类型就得看函数getNalUnitType(),这里就不再展开

xGetBuffer():相当于初始化指针pcPic,设置重建帧指针的指向

后面进行PictureHeader有关的初始设置


const int picWidth = pcPic->cs->pps->getPicWidthInLumaSamples();//帧的宽度
const int picHeight = pcPic->cs->pps->getPicHeightInLumaSamples();//帧的高度
const int maxCUWidth = pcPic->cs->sps->getMaxCUWidth();//CU最大允许宽度
const int maxCUHeight = pcPic->cs->sps->getMaxCUHeight();//CU最大允许高度
const ChromaFormat chromaFormatIDC = pcPic->cs->sps->getChromaFormatIdc();//色度采样格式
const int maxTotalCUDepth = floorLog2(maxCUWidth) - pcPic->cs->sps->getLog2MinCodingBlockSize();//最大CU深度

pcPic->createTempBuffers( pcPic->cs->pps->pcv->maxCUWidth );//创建预测值和残差值的buffer
pcPic->cs->createCoeffs((bool)pcPic->cs->sps->getPLTMode());//创建和TU有关的buffer

pcPic->clearSliceBuffer();//清空slices的buffer
pcPic->allocateNewSlice();//分配一个新的slice
m_pcSliceEncoder->setSliceSegmentIdx(0);//设置m_uiSliceSegmentIdx,表示当前编码slice的Index

m_pcSliceEncoder->initEncSlice(pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField, isEncodeLtRef, m_pcEncLib->getLayerId() );//初始化slice

createTempBuffers():创建预测值和残差值的buffer

createCoeffs():创建和TU有关的buffer

clearSliceBuffer():清空slices的buffer

allocateNewSlice():分配一个新的slice

setSliceSegmentIdx():设置m_uiSliceSegmentIdx,表示当前编码slice的Index

initEncSlice():初始化slice,是需要不停翻看的函数


2.有关slice的设置

pcSlice->setLastIDR(m_iLastIDR);
pcSlice->setIndependentSliceIdx(0);

if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P')
{
   
    pcSlice->setSliceType(P_SLICE);
}
if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I')
{
   
    pcSlice->setSliceType(I_SLICE);
}
pcSlice->setTLayer(m_pcCfg->getGOPEntry(iGOPid).m_temporalId);
pcSlice->setNalUnitType(getNalUnitType(
  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值