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

来源:互联网 发布:电脑修复软件 编辑:程序博客网 时间:2024/06/05 21:15

       一,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 longuint32;
typedef unsigned __int64uint64;
typedef signed charint8;
typedef signed shortint16;
typedef signed longint32;
typedef signed __int64int64;


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

struct vc_params_t{LONG width,height;DWORD profile, level;DWORD nal_length_size;void clear(){memset(this, 0, sizeof(*this));}};


3、定义网络抽象层Nal类 

 class NALBitstream { public: NALBitstream() : m_data(NULL), m_len(0), m_idx(0), m_bits(0), m_byte(0), m_zeros(0)  { }; NALBitstream(void * data, int len)  { Init(data, len);  }; void Init(void * data, int len)  { m_data = (LPBYTE)data; m_len = len; m_idx = 0;  m_bits = 0; m_byte = 0;  m_zeros = 0;  }; BYTE GetBYTE() { if ( m_idx >= m_len ) return 0; BYTE b = m_data[m_idx++]; if ( b == 0 ) { m_zeros++; if ( (m_idx < m_len) && (m_zeros == 2) && (m_data[m_idx] == 0x03) ) { m_idx++; m_zeros=0; } }  else  m_zeros = 0; return b; }; UINT32 GetBit()  { if (m_bits == 0)  { m_byte = GetBYTE(); m_bits = 8; } m_bits--; return (m_byte >> m_bits) & 0x1; }; UINT32 GetWord(int bits)  { UINT32 u = 0; while ( bits > 0 ) { u <<= 1; u |= GetBit(); bits--; } return u; }; UINT32 GetUE()  { int zeros = 0; while (m_idx < m_len && GetBit() == 0 ) zeros++; return GetWord(zeros) + ((1 << zeros) - 1); }; INT32 GetSE() { UINT32 UE = GetUE(); bool positive = UE & 1; INT32 SE = (UE + 1) >> 1; if ( !positive ) { SE = -SE; } return SE; }; private: LPBYTE m_data; int m_len; int m_idx; int m_bits; BYTE m_byte; int m_zeros; }; bool  ParseSequenceParameterSet(BYTE* data,int size, vc_params_t& params) { if (size < 20) {  return false; } NALBitstream bs(data, size); // seq_parameter_set_rbsp() bs.GetWord(4);// sps_video_parameter_set_id int sps_max_sub_layers_minus1 = bs.GetWord(3);  if (sps_max_sub_layers_minus1 > 6)  { return false; } bs.GetWord(1);  { bs.GetWord(2);  bs.GetWord(1);  params.profile = bs.GetWord(5);  bs.GetWord(32);// bs.GetWord(1);//  bs.GetWord(1);//  bs.GetWord(1);//  bs.GetWord(1);//   bs.GetWord(44);//  params.level   = bs.GetWord(8);// general_level_idc uint8 sub_layer_profile_present_flag[6] = {0}; uint8 sub_layer_level_present_flag[6]   = {0}; for (int i = 0; i < sps_max_sub_layers_minus1; i++) { sub_layer_profile_present_flag[i]= bs.GetWord(1); sub_layer_level_present_flag[i]= bs.GetWord(1); } if (sps_max_sub_layers_minus1 > 0)  { for (int i = sps_max_sub_layers_minus1; i < 8; i++) { uint8 reserved_zero_2bits = bs.GetWord(2); } } for (int i = 0; i < sps_max_sub_layers_minus1; i++)  { if (sub_layer_profile_present_flag[i]) { bs.GetWord(2);  bs.GetWord(1);  bs.GetWord(5);/  bs.GetWord(32);  bs.GetWord(1);  bs.GetWord(1);  bs.GetWord(1);  bs.GetWord(1);  bs.GetWord(44);  } if (sub_layer_level_present_flag[i]) { bs.GetWord(8);// sub_layer_level_idc[i] } } } uint32 sps_seq_parameter_set_id= bs.GetUE();   if (sps_seq_parameter_set_id > 15) { return false; } uint32 chroma_format_idc = bs.GetUE();   if (sps_seq_parameter_set_id > 3) { return false; } if (chroma_format_idc == 3) { bs.GetWord(1);//   } params.width  = bs.GetUE(); // pic_width_in_luma_samples params.height  = bs.GetUE(); // pic_height_in_luma_samples if (bs.GetWord(1)) {  bs.GetUE();   bs.GetUE();   bs.GetUE();   bs.GetUE();    } uint32 bit_depth_luma_minus8= bs.GetUE(); uint32 bit_depth_chroma_minus8= bs.GetUE(); if (bit_depth_luma_minus8 != bit_depth_chroma_minus8) { return false; } //... return true; }

 


4、测试代码

 

 int _tmain(int argc, _TCHAR* argv[])   {   vc_params_t params = {0};   BYTE Sps[41] = {0X42,0X01,0X01,0X01,0X60,0X00,0X00,0X03,0X00,0X80,0X00,0X00,0X03,0X00,0X00,
  0X03,0X00,0X5D,0XA0,0X02,0X80, 0X80,0X2D,0X16,0X59,0X5E,0X49,0X32,0XB8,0X04,0X00,0X00,0X03,
  0X00,0X04,0X00,0X00,0X03,0X00,0X64,0X20};  
 ParseSequenceParameterSet(Sps,41,params);   printf("%d-%d-%d\n",params.width,params.height,params.level);   system("pause");   return 0;   } 



原创粉丝点击