h265 Nalu类型判断及 sps 数据解析

      一,Nalu解析                       



 首先来介绍下h265(HEVC)nal单元头,与h264的nal层相比,h265的nal unit header有两个字节构成,如下图所示 

0                   1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| F | Type | LayerId | TID |
+------------ - +---------------- - +
 

其语法如下表中的定义:


nal_unit_header( ) {

Descriptor

     forbidden_zero_bit

f(1)

     nal_unit_type

u(6)

     nuh_reserved_zero_6bits

u(6)

     nuh_temporal_id_plus1

u(3)

}

 

 
从图中可以看出hHEVC的nal包结构与h264有明显的不同,hevc加入了nal所在的时间层的ID,取去除了nal_ref_idc,此信息合并到了naltype中,
通常情况下F为0,layerid为0,  TID为1。



H265 帧类型判断:
和264的&0x1f不同。265是 :
int type = (code & 0x7E)>>1;

在文件中查找00 00 00 01NALU头,发现在有6种开头分别为:


再根据H265的NALU类型定义分析,

        00 00 00 01 40 01  的nuh_unit_type的值为 32, 语义为视频参数集        VPS

       00 00 00 01 42 01  的nuh_unit_type的值为 33, 语义为序列参数集         SPS

       00 00 00 01 44 01  的nuh_unit_type的值为 34, 语义为图像参数集         PPS


       00 00 00 01 4E 01  的nuh_unit_type的值为 39, 语义为补充增强信息       SEI


       00 00 00 01 26 01  的nuh_unit_type的值为 19, 语义为可能有RADL图像的IDR图像的SS编码数据   IDR


       00 00 00 01 02 01  的nuh_unit_type的值为1, 语义为被参考的后置图像,且非TSA、非STSA的SS编码数据


      在编码过程中,从编码器获取码流的时候,1、2、3、4、5是在一帧数据当中。相当于H264的I帧。




Nalu Type的定义


  1. enum NalUnitType  
  2. {  
  3.   NAL_UNIT_CODED_SLICE_TRAIL_N = 0,   // 0  
  4.   NAL_UNIT_CODED_SLICE_TRAIL_R,   // 1  
  5.     
  6.   NAL_UNIT_CODED_SLICE_TSA_N,     // 2  
  7.   NAL_UNIT_CODED_SLICE_TLA,       // 3   // Current name in the spec: TSA_R  
  8.     
  9.   NAL_UNIT_CODED_SLICE_STSA_N,    // 4  
  10.   NAL_UNIT_CODED_SLICE_STSA_R,    // 5  
  11.   
  12.   NAL_UNIT_CODED_SLICE_RADL_N,    // 6  
  13.   NAL_UNIT_CODED_SLICE_DLP,       // 7 // Current name in the spec: RADL_R  
  14.     
  15.   NAL_UNIT_CODED_SLICE_RASL_N,    // 8  
  16.   NAL_UNIT_CODED_SLICE_TFD,       // 9 // Current name in the spec: RASL_R  
  17.   
  18.   NAL_UNIT_RESERVED_10,  
  19.   NAL_UNIT_RESERVED_11,  
  20.   NAL_UNIT_RESERVED_12,  
  21.   NAL_UNIT_RESERVED_13,  
  22.   NAL_UNIT_RESERVED_14,  
  23.   NAL_UNIT_RESERVED_15, NAL_UNIT_CODED_SLICE_BLA,       // 16   // Current name in the spec: BLA_W_LP  
  24. NAL_UNIT_CODED_SLICE_BLA,       // 16   // Current name in the spec: BLA_W_LP  
  25.   NAL_UNIT_CODED_SLICE_BLANT,     // 17   // Current name in the spec: BLA_W_DLP  
  26.   NAL_UNIT_CODED_SLICE_BLA_N_LP,  // 18  
  27.   NAL_UNIT_CODED_SLICE_IDR,       // 19  // Current name in the spec: IDR_W_DLP  
  28.   NAL_UNIT_CODED_SLICE_IDR_N_LP,  // 20  
  29.   NAL_UNIT_CODED_SLICE_CRA,       // 21  
  30.   NAL_UNIT_RESERVED_22,  
  31.   NAL_UNIT_RESERVED_23,  
  32.   
  33.   NAL_UNIT_RESERVED_24,  
  34.   NAL_UNIT_RESERVED_25,  
  35.   NAL_UNIT_RESERVED_26,  
  36.   NAL_UNIT_RESERVED_27,  
  37.   NAL_UNIT_RESERVED_28,  
  38.   NAL_UNIT_RESERVED_29,  
  39.   NAL_UNIT_RESERVED_30,  
  40.   NAL_UNIT_RESERVED_31,  
  41.   
  42.   NAL_UNIT_VPS,                   // 32  
  43.   NAL_UNIT_SPS,                   // 33  
  44.   NAL_UNIT_PPS,                   // 34  
  45.   NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35  
  46.   NAL_UNIT_EOS,                   // 36  
  47.   NAL_UNIT_EOB,                   // 37  
  48.   NAL_UNIT_FILLER_DATA,           // 38  
  49.   NAL_UNIT_SEI,                   // 39 Prefix SEI  
  50.   NAL_UNIT_SEI_SUFFIX,            // 40 Suffix SEI  
  51.   NAL_UNIT_RESERVED_41,  
  52.   NAL_UNIT_RESERVED_42,  
  53.   NAL_UNIT_RESERVED_43,  
  54.   NAL_UNIT_RESERVED_44,  
  55.   NAL_UNIT_RESERVED_45,  
  56.   NAL_UNIT_RESERVED_46,  
  57.   NAL_UNIT_RESERVED_47,  
  58.   NAL_UNIT_UNSPECIFIED_48,  
  59.   NAL_UNIT_UNSPECIFIED_49,  
  60.   NAL_UNIT_UNSPECIFIED_50,  
  61.   NAL_UNIT_UNSPECIFIED_51,  
  62.   NAL_UNIT_UNSPECIFIED_52,  
  63.   NAL_UNIT_UNSPECIFIED_53,  
  64.   NAL_UNIT_UNSPECIFIED_54,  
  65.   NAL_UNIT_UNSPECIFIED_55,  
  66.   NAL_UNIT_UNSPECIFIED_56,  
  67.   NAL_UNIT_UNSPECIFIED_57,  
  68.   NAL_UNIT_UNSPECIFIED_58,  
  69.   NAL_UNIT_UNSPECIFIED_59,  
  70.   NAL_UNIT_UNSPECIFIED_60,  
  71.   NAL_UNIT_UNSPECIFIED_61,  
  72.   NAL_UNIT_UNSPECIFIED_62,  
  73.   NAL_UNIT_UNSPECIFIED_63,  
  74.   NAL_UNIT_INVALID,  
  75. };  

 

     二,     SPS解析                                         

 

1、重新定义类型

typedef unsigned char   uint8;   

typedef unsigned short uint16;

typedef unsigned long uint32;
typedef unsigned __int64 uint64;
typedef signed char int8;
typedef signed short int16;
typedef signed long int32;
typedef signed __int64 int64;


2、定义Sps 需要的相关参数

[cpp]  view plain  copy
  1. struct vc_params_t  
  2. {  
  3.     LONG width,height;  
  4.     DWORD profile, level;  
  5.     DWORD nal_length_size;  
  6.     void clear()  
  7.     {  
  8.         memset(this, 0, sizeof(*this));  
  9.     }  
  10. };  


3、定义网络抽象层Nal类 

[cpp]  view plain  copy
  1. class NALBitstream  
  2. {  
  3. public:  
  4.  NALBitstream() : m_data(NULL), m_len(0), m_idx(0), m_bits(0), m_byte(0), m_zeros(0)   
  5.  {  
  6.   
  7.  };  
  8.  NALBitstream(void * data, int len)   
  9.  {  
  10.      Init(data, len);   
  11.  };  
  12.  void Init(void * data, int len)   
  13.  {  
  14.      m_data = (LPBYTE)data;  
  15.      m_len = len;  
  16.      m_idx = 0;   
  17.      m_bits = 0;  
  18.      m_byte = 0;   
  19.      m_zeros = 0;   
  20.  };  
  21.  BYTE GetBYTE()  
  22.  {  
  23.      if ( m_idx >= m_len )  
  24.          return 0;  
  25.      BYTE b = m_data[m_idx++];  
  26.      if ( b == 0 )  
  27.      {  
  28.          m_zeros++;  
  29.          if ( (m_idx < m_len) && (m_zeros == 2) && (m_data[m_idx] == 0x03) )  
  30.          {  
  31.              m_idx++;  
  32.              m_zeros=0;  
  33.          }  
  34.      }   
  35.      else  m_zeros = 0;  
  36.   
  37.      return b;  
  38.  };  
  39.   
  40.  UINT32 GetBit()   
  41.  {  
  42.      if (m_bits == 0)   
  43.      {  
  44.          m_byte = GetBYTE();  
  45.          m_bits = 8;  
  46.      }  
  47.      m_bits--;  
  48.      return (m_byte >> m_bits) & 0x1;  
  49.  };  
  50.   
  51.  UINT32 GetWord(int bits)   
  52.  {  
  53.      UINT32 u = 0;  
  54.      while ( bits > 0 )  
  55.      {  
  56.          u <<= 1;  
  57.          u |= GetBit();  
  58.          bits--;  
  59.      }  
  60.      return u;  
  61.  };  
  62.   
  63.  UINT32 GetUE()   
  64.  {  
  65.      int zeros = 0;  
  66.      while (m_idx < m_len && GetBit() == 0 ) zeros++;  
  67.      return GetWord(zeros) + ((1 << zeros) - 1);  
  68.  };  
  69.   
  70.  INT32 GetSE()  
  71.  {  
  72.      UINT32 UE = GetUE();  
  73.      bool positive = UE & 1;  
  74.      INT32 SE = (UE + 1) >> 1;  
  75.      if ( !positive )  
  76.      {  
  77.          SE = -SE;  
  78.      }  
  79.      return SE;  
  80.  };  
  81. private:  
  82.  LPBYTE m_data;  
  83.  int m_len;  
  84.  int m_idx;  
  85.  int m_bits;  
  86.  BYTE m_byte;  
  87.  int m_zeros;  
  88. };  
  89.   
  90. bool  ParseSequenceParameterSet(BYTE* data,int size, vc_params_t& params)  
  91. {  
  92.  if (size < 20)  
  93.  {   
  94.      return false;  
  95.  }  
  96.  NALBitstream bs(data, size);  
  97.  // seq_parameter_set_rbsp()  
  98.  bs.GetWord(4);// sps_video_parameter_set_id  
  99.  int sps_max_sub_layers_minus1 = bs.GetWord(3);   
  100.  if (sps_max_sub_layers_minus1 > 6)   
  101.  {  
  102.      return false;  
  103.  }  
  104.  bs.GetWord(1);   
  105.  {  
  106.      bs.GetWord(2);   
  107.      bs.GetWord(1);   
  108.      params.profile = bs.GetWord(5);   
  109.      bs.GetWord(32);//  
  110.      bs.GetWord(1);//   
  111.      bs.GetWord(1);//   
  112.      bs.GetWord(1);//   
  113.      bs.GetWord(1);//    
  114.      bs.GetWord(44);//   
  115.      params.level   = bs.GetWord(8);// general_level_idc  
  116.      uint8 sub_layer_profile_present_flag[6] = {0};  
  117.      uint8 sub_layer_level_present_flag[6]   = {0};  
  118.      for (int i = 0; i < sps_max_sub_layers_minus1; i++) {  
  119.          sub_layer_profile_present_flag[i]= bs.GetWord(1);  
  120.          sub_layer_level_present_flag[i]= bs.GetWord(1);  
  121.      }  
  122.      if (sps_max_sub_layers_minus1 > 0)   
  123.      {  
  124.          for (int i = sps_max_sub_layers_minus1; i < 8; i++) {  
  125.              uint8 reserved_zero_2bits = bs.GetWord(2);  
  126.          }  
  127.      }  
  128.      for (int i = 0; i < sps_max_sub_layers_minus1; i++)   
  129.      {  
  130.          if (sub_layer_profile_present_flag[i]) {  
  131.              bs.GetWord(2);   
  132.              bs.GetWord(1);   
  133.              bs.GetWord(5);/   
  134.                  bs.GetWord(32);   
  135.              bs.GetWord(1);   
  136.              bs.GetWord(1);   
  137.              bs.GetWord(1);   
  138.              bs.GetWord(1);   
  139.              bs.GetWord(44);   
  140.          }  
  141.          if (sub_layer_level_present_flag[i]) {  
  142.              bs.GetWord(8);// sub_layer_level_idc[i]  
  143.          }  
  144.      }  
  145.  }  
  146.  uint32 sps_seq_parameter_set_id= bs.GetUE();    
  147.  if (sps_seq_parameter_set_id > 15) {  
  148.      return false;  
  149.  }  
  150.  uint32 chroma_format_idc = bs.GetUE();    
  151.  if (sps_seq_parameter_set_id > 3) {  
  152.      return false;  
  153.  }  
  154.  if (chroma_format_idc == 3) {  
  155.      bs.GetWord(1);//    
  156.  }  
  157.  params.width  = bs.GetUE(); // pic_width_in_luma_samples  
  158.  params.height  = bs.GetUE(); // pic_height_in_luma_samples  
  159.  if (bs.GetWord(1)) {   
  160.      bs.GetUE();    
  161.      bs.GetUE();    
  162.      bs.GetUE();    
  163.      bs.GetUE();     
  164.  }  
  165.  uint32 bit_depth_luma_minus8= bs.GetUE();  
  166.  uint32 bit_depth_chroma_minus8= bs.GetUE();  
  167.  if (bit_depth_luma_minus8 != bit_depth_chroma_minus8) {  
  168.      return false;  
  169.  }  
  170.  //...  
  171.  return true;  
  172. }  

 


4、测试代码

 

[cpp]  view plain  copy
  1. int _tmain(int argc, _TCHAR* argv[])    
  2. {    
  3.  vc_params_t params = {0};    
  4.  BYTE Sps[41] = {0X42,0X01,0X01,0X01,0X60,0X00,0X00,0X03,0X00,0X80,0X00,0X00,0X03,0X00,0X00,  
[cpp]  view plain  copy
  1. <span style="white-space:pre;"> </span>  0X03,0X00,0X5D,0XA0,0X02,0X80, 0X80,0X2D,0X16,0X59,0X5E,0X49,0X32,0XB8,0X04,0X00,0X00,0X03,  
[cpp]  view plain  copy
  1. <span style="white-space:pre;"> </span>  0X00,0X04,0X00,0X00,0X03,0X00,0X64,0X20};    
[cpp]  view plain  copy
  1.  ParseSequenceParameterSet(Sps,41,params);    
  2.  printf("%d-%d-%d\n",params.width,params.height,params.level);    
  3.  system("pause");    
  4.  return 0;    
  5. }   

转自:http://blog.csdn.net/machh/article/details/72190321

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值