VVC/H.266代码阅读(VTM8.0)(一. NALU提取)

网上很多大佬对VVC的代码进行过分析,基本都是从编码端入手。
考虑到从解码端分析代码,一是更加简单(解码流程无需编码工具和编码参数的择优),二是可以配合Draft文本更好地理解视频编解码的流程(解码端也都包含预测、量化、环路滤波、熵解码等流程),所以我想从解码端入手分析一下VVC大致的流程。等到解码端代码分析完后,可以再从编码端深入分析一下。

本文是本系列的第一篇博客,内容是分析解码端将收到的二进制码流bin文件提取成一个个NALU的过程。

该系列相关博客为:
VVC/H.266代码阅读(VTM8.0)(一. NALU提取)
VVC/H.266代码阅读(VTM8.0)(二. non-VCLU解码)
VVC/H.266代码阅读(VTM8.0)(三. Slice到CTU的处理 )
VVC/H.266代码阅读(VTM8.0)(四. CU划分 )

VVC/H.266常见资源为:
VVC/H.266常见资源整理(提案地址、代码、资料等)

注:

  1. 本文分析的bin文件是利用VTM8.0的编码器,以All Intra配置(IBC 打开)编码100帧得到的二进制码流(TemporalSubsampleRatio: 8,实际编码 ⌈100 / 8⌉ = 13帧)。
  2. 解码用最简单的:-b str.bin -o dec.yuv

1. 入口函数是decmain.cpp 中的main()函数

(1) main函数先会打印若干信息,比如设备信息。
(2) 调用 DecAppCfg::parseCfg() 解析输入参数,如本文所用的bin文件的名字、重建YUV文件的名字等信息。
(3) 调用 DecApp::decode() 开启解码流程。

2. DecApp::decode()函数

(1) 首先构造了名为nalu的 InputNALUnit 类。

InputNALUnit nalu;

① InputNALUnit是NALUnit的子类,NALUnit类中包含NalUnitType、temporalId等相关信息、还含有判断当前NALU是不是VCLU和SliceNALU的成员函数isVcl() 、isSlice()。
② 此外,InputNALUnit多包含了名为m_Bitstream数据成员(InputBitstream类)。
③ InputBitstream类中的m_fifo数据成员以FIFO顺序存储当前NALU的Bytes数据。

class InputNALUnit : public NALUnit
{
   
   
  private:
    InputBitstream m_Bitstream;
  ……
};
struct NALUnit
{
   
   
  NalUnitType     m_nalUnitType; ///< nal_unit_type
  uint32_t        m_temporalId;  ///< temporal_id
  uint32_t        m_nuhLayerId;  ///< nuh_layer_id
  uint32_t        m_forbiddenZeroBit;
  uint32_t        m_nuhReservedZeroBit;
  ……
}

(2) 然后判断下一个NALU是不是新图像/AU的第一个NALU。

check if next NAL unit will be the first NAL unit from a new picture or access unit

bool bNewPicture = isNewPicture(&bitstreamFile, &bytestream);
bool bNewAccessUnit = bNewPicture && isNewAccessUnit( bNewPicture, &bitstreamFile, &bytestream );
bool DecApp::isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytestream)
{
   
   
  // cannot be a new picture if there haven't been any slices yet、
  //该函数检查Declib::m_bFirstSliceInPicture变量,见下段代码。
  if(m_cDecLib.getFirstSliceInPicture())
  {
   
   
    return false;
  }
  ……
bool  getFirstSliceInPicture () const  
{
   
    return m_bFirstSliceInPicture; }

Declib::m_bFirstSliceInPicture是一个bool值,该bool值默认为true。在DecSlice::decompressSlice()之后,该值会被设置为false,表示一个slice编码完毕。然后isNewPicture()函数会预先读取下一个NALU的NalUnitType,例如,如果下一个NALU是SPS、PPS等参数集,那就说明是新的图像的新NALU,返回True。

3. bNewPicture == false,进入NALU的提取环节,为本文的分析重点。否则进入第4步,完成该帧的后续处理和输出环节。
(1) 调用byteStreamNALUnit() 解析当前NALU。该函数核心调用_byteStreamNALUnit()。

// find next NAL 
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值