当前位置:网站首页>H265 Nalu类型判断及 sps 数据解析
H265 Nalu类型判断及 sps 数据解析
2022-06-10 20:00:00 【用户3504492】
一,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) |
} |
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 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 NAL_UNIT_CODED_SLICE_RASL_N, // 8 NAL_UNIT_CODED_SLICE_TFD, // 9 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 NAL_UNIT_CODED_SLICE_BLA, // 16 NAL_UNIT_CODED_SLICE_BLANT, // 17 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, };
通过录制H265的ES流,进行分析NALU头,发现在有6种开头分别为:
1) 00 00 00 01 40 01
2) 00 00 00 01 42 01
3) 00 00 00 01 44 01
4) 00 00 00 01 4E 01
5) 00 00 00 01 26 01
6) 00 00 00 01 02 01
再根据H265的NALU类型定义分析,
00 00 00 01 40 01 的nuh_unit_type的值为32, 语义为视频参数集
00 00 00 01 42 01 的nuh_unit_type的值为33, 语义为序列参数集
00 00 00 01 44 01 的nuh_unit_type的值为34, 语义为图像参数集
00 00 00 01 4E 01 的nuh_unit_type的值为39, 语义为补充增强信息
00 00 00 01 26 01 的nuh_unit_type的值为19, 语义为可能有RADL图像的IDR图像的SS编码数据
00 00 00 01 02 01 的nuh_unit_type的值为1, 语义为被参考的后置图像,且非TSA、非STSA的SS编码数据
在编码过程中,从编码器获取码流的时候,1、2、3、4、5是在一帧数据当中。相当于H264的I帧。
二,SPS解析
一段HEVC码流可能包含一个或者多个编码视频序列CVS,每个CVS由一个随机接入点开始,即 IDR/BLA/CRA。在H.264和HEVC中,序列参数集SPS包含该CVS中所有slice需要的信息。SPS的内容大致可以分为几个部分:
1、自引ID;
2、解码相关信息,如档次级别、分辨率、子层数等;
3、某档次中的功能开关标识及该功能的参数;
4、对结构和变换系数编码灵活性的限制信息;
5、时域可分级信息;
6、VUI。
以下是对每一个语法元素的讨论解释:
1、sps_video_parameter_set_id :指定了当前活动的VPS的ID号,当前例子的取值为0,这也与前文的VPS解析的结果一直;
2、sps_max_sub_layers_minus1 : 该值+1表示引用该SPS的CVS所包含的最大时域子层数,取值范围0-6;本例取值为0,即只有1个时域子层;
3、sps_temporal_id_nesting_flag :标识时域可分级中的帧间预测参考帧的限制信息;此处该值取0【好像与标准文档里写的有点矛盾啊……】;
4、sps_seq_parameter_set_id :【其实在这个参数之前码流中还有很多数据没有解释清楚,留到以后看吧】本SPS的ID值,此处取0;
5、chroma_format_idc:色度采样格式,此处取值为1,代表采用4:2:0格式;
6、separate_colour_plane_flag :这个参数是4:4:4格式专用的,在本例中不存在;
7、pic_width_in_luma_samples和pic_height_in_luma_samples :图像的分辨率信息,用指数哥伦布编码,本例取176*144;
8、conformance_window_flag :指示一致窗口裁剪偏移参数conformance cropping window offset parameters的信息;此处取值为1,表示后续几位为conf_win_left_offset、conf_win_right_offset、conf_win_top_offset、conf_win_bottom_offset等参数;
9、bit_depth_luma_minus8 :指定了亮度矩阵的比特深度以及亮度量化参数范围偏移量;此处取0,表示每个亮度像素用8为表示,QpBdOffset参数为0;
10、bit_depth_chroma_minus8 :与bit_depth_luma_minus8类似,只不过是针对色度的;
11、log2_max_pic_order_cnt_lsb_minus4 :负责计算变量MaxPicOrderCntLsb的值【这个值是干嘛的……】;
12、sps_sub_layer_ordering_info_present_flag :时域子层顺序标识开关,该值取1,表示后续几位分别是sps_max_dec_pic_buffering、sps_num_reorder_pics、sps_max_latency_increase等参数;
13、log2_min_coding_block_size_minus3 :用于计算最小亮度CB的尺寸,此处取0;
14、log2_diff_max_min_coding_block_size :用于计算最大最小亮度CB尺寸的差值,此处取3;
15、log2_min_transform_block_size_minus2:用于计算最小TB尺寸,此处取0;
16、log2_diff_max_min_transform_block_size :用于计算最大最小TB尺寸的差值,此处取3;
17、max_transform_hierarchy_depth_inter :帧间模式CB中TB的最大层级深度,此处为2;
18、max_transform_hierarchy_depth_intra ::帧内模式CB中TB的最大层级深度,此处为2;
19、scaling_list_enabled_flag:标识是否在变换系数量化中使用量化列表,此处取0;
20、amp_enabled_flag :标识是否使用不对称运动划分,此处为1;
21、sample_adaptive_offset_enabled_flag :标识是否使用SAO,此处为1;
22、pcm_enabled_flag :标识是否使用PCM,此处为0,即不实用PCM数据;
23、num_short_term_ref_pic_sets :指示SPS中short_term_ref_pic_set( )这个结构的数目,此处为1;
24、long_term_ref_pics_present_flag :指示帧间预测中是否使用长期参考帧,此处为1,即使用长期参考帧;
25、sps_temporal_mvp_enable_flag :标识CVS中非IDR帧的条带头中是否包含slice_temporal_mvp_enabled_flag标识,此处为1,即含有;
26、sps_strong_intra_smoothing_enable_flag :标识平滑滤波过程中是否使用双线性差值方法,此处为1,即使用;
27、vui_parameters_present_flag :标识是否有
以下是解析代码
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;
//...
}4、测试代码
边栏推荐
- Is Zhongyan futures a regular platform in China? Is it safe to open an account? Want to open a futures account
- 蛮力法/u到v是否存在简单路径
- Quick start to elastic job, three minutes to experience distributed scheduled tasks
- 35岁被裁员,还能拥有美妙人生吗?
- 解决idea超过5个相同包的时候自动变成*的问题
- Talk about server performance optimization ~ (recommended Collection)
- redis设置密码命令(临时密码)
- 记录一下今天的MySQL故障
- Cas de test app
- Identity and access management (IAM)
猜你喜欢

面试必备——synchronized底层原理的基础知识

vulnhub-The Planets: Earth

Test APK exception control netlocation attacker development

Connexion MySQL errorcode 1129, State hy000, Host 'xxx' is Blocked because of many Connection Errors

pdf. Js----- JS parse PDF file to realize preview, and obtain the contents in PDF file (in array form)

pdf.js-----js解析pdf文件实现预览,并获取pdf文件中的内容(数组形式)

LeetCode:1037. Effective boomerang - simple

解决idea超过5个相同包的时候自动变成*的问题

Game compatibility test (general scheme)

Elastic-Job的快速入门,三分钟带你体验分布式定时任务
随机推荐
KCon 2022 议题大众评选火热进行中!不要错过“心仪”的议题哦~
MySQL - common functions
牛客网:数组中出现次数超过一半的数字
In depth learning experience and tools
服务管理与通信,基础原理分析
vulnhub-The Planets: Earth
Electronic bidding procurement mall system: optimize traditional procurement business and speed up enterprise digital upgrading
72. editing distance ●●
The most common habits from more than 200 English papers written by gradua
LeetCode:1037. Effective boomerang - simple
shell实现ssh登录并执行命令
H5 van popup full screen pop-up window, simulates the page fallback effect, supports the return button in the upper left corner, and is suitable for physical return, side sliding and bottom return key
Node (express) implements interfaces such as adding, deleting, modifying, and paging
Kcon 2022 topic public selection is hot! Don't miss the topic of "favorite"
Read the source code of micropyton - add the C extension class module (2)
蛮力法/1~n的全排列 v3 递归
知识图谱/关系可视化
Monitoring is easy to create a "quasi ecological" pattern and empower Xinchuang to "replace"
canvas 高级功能(中)
力扣1082,1084题解_sql查询类型的题目