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)
}
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的定义
- enum NalUnitType
- {
- NAL_UNIT_CODED_SLICE_TRAIL_N = 0, // 0
- NAL_UNIT_CODED_SLICE_TRAIL_R, // 1
- NAL_UNIT_CODED_SLICE_TSA_N, // 2
- NAL_UNIT_CODED_SLICE_TLA, // 3 // Current name in the spec: TSA_R
- NAL_UNIT_CODED_SLICE_STSA_N, // 4
- NAL_UNIT_CODED_SLICE_STSA_R, // 5
- NAL_UNIT_CODED_SLICE_RADL_N, // 6
- NAL_UNIT_CODED_SLICE_DLP, // 7 // Current name in the spec: RADL_R
- NAL_UNIT_CODED_SLICE_RASL_N, // 8
- NAL_UNIT_CODED_SLICE_TFD, // 9 // Current name in the spec: RASL_R
- NAL_UNIT_RESERVED_10,
- NAL_UNIT_RESERVED_11,
- NAL_UNIT_RESERVED_12,
- NAL_UNIT_RESERVED_13,
- NAL_UNIT_RESERVED_14,
- NAL_UNIT_RESERVED_15, NAL_UNIT_CODED_SLICE_BLA, // 16 // Current name in the spec: BLA_W_LP
- NAL_UNIT_CODED_SLICE_BLA, // 16 // Current name in the spec: BLA_W_LP
- NAL_UNIT_CODED_SLICE_BLANT, // 17 // Current name in the spec: BLA_W_DLP
- NAL_UNIT_CODED_SLICE_BLA_N_LP, // 18
- NAL_UNIT_CODED_SLICE_IDR, // 19 // Current name in the spec: IDR_W_DLP
- NAL_UNIT_CODED_SLICE_IDR_N_LP, // 20
- NAL_UNIT_CODED_SLICE_CRA, // 21
- NAL_UNIT_RESERVED_22,
- NAL_UNIT_RESERVED_23,
- NAL_UNIT_RESERVED_24,
- NAL_UNIT_RESERVED_25,
- NAL_UNIT_RESERVED_26,
- NAL_UNIT_RESERVED_27,
- NAL_UNIT_RESERVED_28,
- NAL_UNIT_RESERVED_29,
- NAL_UNIT_RESERVED_30,
- NAL_UNIT_RESERVED_31,
- NAL_UNIT_VPS, // 32
- NAL_UNIT_SPS, // 33
- NAL_UNIT_PPS, // 34
- NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35
- NAL_UNIT_EOS, // 36
- NAL_UNIT_EOB, // 37
- NAL_UNIT_FILLER_DATA, // 38
- NAL_UNIT_SEI, // 39 Prefix SEI
- NAL_UNIT_SEI_SUFFIX, // 40 Suffix SEI
- NAL_UNIT_RESERVED_41,
- NAL_UNIT_RESERVED_42,
- NAL_UNIT_RESERVED_43,
- NAL_UNIT_RESERVED_44,
- NAL_UNIT_RESERVED_45,
- NAL_UNIT_RESERVED_46,
- NAL_UNIT_RESERVED_47,
- NAL_UNIT_UNSPECIFIED_48,
- NAL_UNIT_UNSPECIFIED_49,
- NAL_UNIT_UNSPECIFIED_50,
- NAL_UNIT_UNSPECIFIED_51,
- NAL_UNIT_UNSPECIFIED_52,
- NAL_UNIT_UNSPECIFIED_53,
- NAL_UNIT_UNSPECIFIED_54,
- NAL_UNIT_UNSPECIFIED_55,
- NAL_UNIT_UNSPECIFIED_56,
- NAL_UNIT_UNSPECIFIED_57,
- NAL_UNIT_UNSPECIFIED_58,
- NAL_UNIT_UNSPECIFIED_59,
- NAL_UNIT_UNSPECIFIED_60,
- NAL_UNIT_UNSPECIFIED_61,
- NAL_UNIT_UNSPECIFIED_62,
- NAL_UNIT_UNSPECIFIED_63,
- NAL_UNIT_INVALID,
- };
二, 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; }
- h265 Nalu类型判断及 sps 数据解析
- h265 sps 数据解析
- H265 帧类型判断
- h.264码流解析_一个SPS的nalu及获取视频的分辨率
- H.264码流解析 一个SPS的nalu及获取视频的分辨率
- H.264码流解析 一个SPS的nalu及获取视频的分辨率
- H.264码流解析 一个SPS的nalu及获取视频的分辨率
- H.264码流解析 一个SPS的nalu及获取视频的分辨率
- H.264码流解析 一个SPS的nalu及获取视频的分辨率
- h264 Nalu 详解(转载) 及 sps.pps.idr相关
- H264--NALU/SPS/PPS
- SPS PPS NALU
- H264码流解析及NALU
- SPS、PPS、IDR以及NALU编码规律
- 一步一步解析H.264码流的NALU(SPS,PSS,IDR)获取宽高和帧率
- H265帧类型
- H265帧类型
- mp4解析h265
- Python运算符和表达式
- Java配置文档
- MVP设计模式的写法
- 数据结构与算法(22)——二叉搜索树
- HTTP Status 500
- h265 Nalu类型判断及 sps 数据解析
- java工具类——java将一串数据按照gzip方式压缩和解压缩
- java在线阅览pdf方法一:pdf.js
- 改变libreoffice的writer背景颜色
- openfire学习笔记二
- 无线智能风扇软件端APP设计
- Java 线程池 Executor框架(1)ThreadPoolExecutor
- HTTP协议学习笔记九
- linux解压命令大全