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進行分析,如下:

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


 

發佈了97 篇原創文章 · 獲贊 855 · 訪問量 106萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章