一、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 | +———— – +—————- – +其语法如下表中的定义:
从图中可以看出hevc的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的定义
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解析代码
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); // “The value of sps_max_sub_layers_minus1 shall be in the range of 0 to 6, inclusive.” if (sps_max_sub_layers_minus1 > 6) { return false; } bs.GetWord(1);// sps_temporal_id_nesting_flag // profile_tier_level( sps_max_sub_layers_minus1 ) { bs.GetWord(2);// general_profile_space bs.GetWord(1);// general_tier_flag params.profile = bs.GetWord(5);// general_profile_idc bs.GetWord(32);// general_profile_compatibility_flag[32] bs.GetWord(1);// general_progressive_source_flag bs.GetWord(1);// general_interlaced_source_flag bs.GetWord(1);// general_non_packed_constraint_flag bs.GetWord(1);// general_frame_only_constraint_flag bs.GetWord(44);// general_reserved_zero_44bits 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);// sub_layer_profile_space[i] bs.GetWord(1);// sub_layer_tier_flag[i] bs.GetWord(5);// sub_layer_profile_idc[i] bs.GetWord(32);// sub_layer_profile_compatibility_flag[i][32] bs.GetWord(1);// sub_layer_progressive_source_flag[i] bs.GetWord(1);// sub_layer_interlaced_source_flag[i] bs.GetWord(1);// sub_layer_non_packed_constraint_flag[i] bs.GetWord(1);// sub_layer_frame_only_constraint_flag[i] bs.GetWord(44);// sub_layer_reserved_zero_44bits[i] } if (sub_layer_level_present_flag[i]) { bs.GetWord(8);// sub_layer_level_idc[i] } } } uint32 sps_seq_parameter_set_id= bs.GetUE(); // “The value of sps_seq_parameter_set_id shall be in the range of 0 to 15, inclusive.” if (sps_seq_parameter_set_id > 15) { return false; } uint32 chroma_format_idc = bs.GetUE(); // “The value of chroma_format_idc shall be in the range of 0 to 3, inclusive.” if (sps_seq_parameter_set_id > 3) { return false; } if (chroma_format_idc == 3) { bs.GetWord(1);// separate_colour_plane_flag } params.width = bs.GetUE(); // pic_width_in_luma_samples params.height = bs.GetUE(); // pic_height_in_luma_samples if (bs.GetWord(1)) {// conformance_window_flag bs.GetUE(); // conf_win_left_offset bs.GetUE(); // conf_win_right_offset bs.GetUE(); // conf_win_top_offset bs.GetUE(); // conf_win_bottom_offset } 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; }三、测试代码
int main(int argc, _TCHAR* argv[]) { vc_params_t params = {0}; BYTE sps1080[] = {0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x7b,0xa0,0x03,0xc0,0x80,0x10,0xe5,0x8d,0xae,0x49,0x32,0xf4,0xdc,0x04,0x04,0x04,0x02}; BYTE sps720[]={0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5d,0xa0,0x02,0x80,0x80,0x2d,0x16,0x36,0xb9,0x24,0xcb,0xd3,0x70,0x10,0x10,0x10,0x08}; BYTE spsD1[]={0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5a,0xa0,0x05,0xa2,0x00,0x90,0x58,0xda,0xe4,0x93,0x2f,0x4d,0xc0,0x40,0x40,0x40,0x20}; ParseSequenceParameterSet(sps1080,sizeof(sps1080),params); printf(“%d-%d-%d\n”,params.width,params.height,params.level); ParseSequenceParameterSet(sps720,sizeof(sps720),params); printf(“%d-%d-%d\n”,params.width,params.height,params.level); ParseSequenceParameterSet(spsD1,sizeof(spsD1),params); printf(“%d-%d-%d\n”,params.width,params.height,params.level); return 0; }免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:h265 sps 解析视频宽高 https://www.yhzz.com.cn/a/17459.html