[置顶] HEVC学习(十九) —— NAL unit 的解码过程之三

前面两篇已经将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进行分析,如下:

[置顶] HEVC学习(十九) —— NAL unit 的解码过程之三_第1张图片

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 );
  }
}


 

你可能感兴趣的:(hm,HEVC,NAL,解码过程)