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



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