NAL unit 解码(三)

本文详细介绍了视频编码中NAL单元的解析过程,重点讲解了如何将NAL单元的payload部分从EBSP转换为RBSP,并给出了具体实现代码。通过去除无效字符和cabac_zero_word等步骤完成转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面两篇已经将NAL的解析过程的核心部分介绍完了,本篇主要讨论如何将NAL的payload部分转化为原始数据,即从EBSP到RBSP的过程。

该过程由TAppDecTop::decode()的子函数read(nalu, nalUnit)调用convertPayloadToRBSP(nalUnitBuf, pcBitstream, (nalUnitBuf[0] & 64) == 0)实现。

read(nalu, nalUnit); //!< nalUnit-->nalu (EBSP-->RBSP)  


/** 
 * create a NALunit structure with given header values and storage for 
 * a bitstream 
 */  
void read(InputNALUnit& nalu, vector<uint8_t>& nalUnitBuf)  
{  
  /* perform anti-emulation prevention */  
  TComInputBitstream *pcBitstream = new TComInputBitstream(NULL);  
#if HM9_NALU_TYPES  
  convertPayloadToRBSP(nalUnitBuf, pcBitstream, (nalUnitBuf[0] & 64) == 0); //!< 实现真正的EBSP-->RBSP  
#else  
  convertPayloadToRBSP(nalUnitBuf, pcBitstream);  
#endif  
    
  nalu.m_Bitstream = new TComInputBitstream(&nalUnitBuf);  
  delete pcBitstream;  
  readNalUnitHeader(nalu); //!< 解析NAL的头部  
}  

#if HM9_NALU_TYPES  
static void convertPayloadToRBSP(vector<uint8_t>& nalUnitBuf, TComInputBitstream *pcBitstream, Bool isVclNalUnit)  
#else  
static void convertPayloadToRBSP(vector<uint8_t>& nalUnitBuf, TComInputBitstream *pcBitstream)  
#endif  
{  
  UInt zeroCount = 0;  
  vector<uint8_t>::iterator it_read, it_write;  
  
  for (it_read = it_write = nalUnitBuf.begin(); it_read != nalUnitBuf.end(); it_read++, it_write++)  
  {  
    assert(zeroCount < 2 || *it_read >= 0x03);  
    if (zeroCount == 2 && *it_read == 0x03) //!< 读到0x000003时,丢弃0x03  
    {  
      it_read++;  
      zeroCount = 0;  
      if (it_read == nalUnitBuf.end())  
      {  
        break;  
      }  
    }  
    zeroCount = (*it_read == 0x00) ? zeroCount+1 : 0;  
    *it_write = *it_read;  
  }  
  assert(zeroCount == 0);  
    
#if HM9_NALU_TYPES  
  if (isVclNalUnit)  
  {  
    // Remove cabac_zero_word from payload if present  
    Int n = 0;  
      
    while (it_write[-1] == 0x00)  
    {  
      it_write--;  
      n++;  
    }  
      
    if (n > 0)  
    {  
      printf("\nDetected %d instances of cabac_zero_word", n/2);        
    }  
  }  
#endif  
  
  nalUnitBuf.resize(it_write - nalUnitBuf.begin());  
}  

下面这个函数可对照draft 7.3.1.2 NAL unit header syntax进行分析,如下:


Void readNalUnitHeader(InputNALUnit& nalu)  
{  
  TComInputBitstream& bs = *nalu.m_Bitstream;  
  
  Bool forbidden_zero_bit = bs.read(1);           // forbidden_zero_bit  
  assert(forbidden_zero_bit == 0);  
  nalu.m_nalUnitType = (NalUnitType) bs.read(6);  // nal_unit_type  
  nalu.m_reservedZero6Bits = bs.read(6);       // nuh_reserved_zero_6bits  
  assert(nalu.m_reservedZero6Bits == 0);  
  nalu.m_temporalId = bs.read(3) - 1;             // nuh_temporal_id_plus1  
  
  if ( nalu.m_temporalId )  
  {  
    assert( nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_BLA  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_BLANT  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_BLA_N_LP  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR_N_LP  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_CRA  
         && nalu.m_nalUnitType != NAL_UNIT_VPS  
         && nalu.m_nalUnitType != NAL_UNIT_SPS  
         && nalu.m_nalUnitType != NAL_UNIT_EOS  
         && nalu.m_nalUnitType != NAL_UNIT_EOB );  
  }  
  else  
  {  
    assert( nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_TLA  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_TSA_N  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_STSA_R  
         && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_STSA_N );  
  }  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值