赞
踩
H.264 中的 SPS(Sequence Parameter Set)是一种参数集,用于描述视频序列的特征和配置信息。SPS 是在 H.264 视频流中的一个元数据单元,它包含了视频编码器的设置和视频序列的特性。
SPS 包含了以下重要的信息:
- // SPS
- typedef struct {
- uint32_t profile_idc; //!< 当前H.264的编码配置, baseline(66) | main(77) | extended(88)
- uint32_t constraint_set0_flag;
- uint32_t constraint_set1_flag;
- uint32_t constraint_set2_flag;
- uint32_t constraint_set3_flag;
- uint32_t constraint_set4_flag;
- uint32_t constraint_set5_flag;
- uint32_t reserved_zero_2bits;
- uint32_t level_idc; //!< 编码等级 0~51
- uint32_t seq_parameter_set_id;
- // if(profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144) {
- uint32_t chroma_format_idc;
- // if( chroma_format_idc = = 3 )
- uint32_t residual_colour_transform_flag;
- // }
- uint32_t bit_depth_luma_minus8;
- uint32_t bit_depth_chroma_minus8;
- uint32_t qpprime_y_zero_transform_bypass_flag;
- uint32_t seq_scaling_matrix_present_flag;
- // if (seq_scaling_matrix_present_flag)
- // for(i = 0; i < 8; i++) {
- uint32_t seq_scaling_list_present_flag[12];
- // }
- // }
- // }
- uint32_t log2_max_frame_num_minus4;
- uint32_t pic_order_cnt_type;
- // if(pic_order_cnt_type == 0) {
- uint32_t log2_max_pic_order_cnt_lsb_minus4;
- // }
- // else if(pic_order_cnt_type == 1) {
- uint32_t delta_pic_order_always_zero_flag;
- int offset_for_non_ref_pic;
- int offset_for_top_to_bottom_field;
- uint32_t num_ref_frames_in_pic_order_cnt_cycle;
- int offset_for_ref_frame[256];
- // }
- uint32_t max_num_ref_frames; //!< 参考帧的最大数目
- uint32_t gaps_in_frame_num_value_allowed_flag;
- uint32_t pic_width_in_mbs_minus1; //!< 用于计算图像的宽度,单位为宏块个数
- uint32_t pic_height_in_map_units_minus1; //!< 度量视频中一帧图像的高度
- uint32_t frame_mbs_only_flag;
- // if (!frame_mbs_only_flag) {
- uint32_t mb_adaptive_frame_field_flag;
- // }
- uint32_t direct_8x8_inference_flag;
- uint32_t frame_cropping_flag;
- // if (frame_cropping_flag) {
- uint32_t frame_crop_left_offset;
- uint32_t frame_crop_right_offset;
- uint32_t frame_crop_top_offset;
- uint32_t frame_crop_bottom_offset;
- // }
- uint32_t vui_parameters_present_flag;
- // if (vui_parameters_present_flag) {
- NaluSpsVuiParameters vui_parameters;
- // }
- } NaluSPS;
- /// 解析SPS头信息
- bool parse_nalu_sps(uint8_t *sps_data, uint32_t sps_size, NaluSPS &sps) {
- if (sps_size < 4)
- return false;
-
- /// 找到 SPS NAL 单元的起始位置
- int start_code_length = 0;
- if (sps_data[0] == 0 && sps_data[1] == 0 && sps_data[2] == 1) { // TODO: 00 00 01
- start_code_length = 3;
- } else if (sps_data[0] == 0 && sps_data[1] == 0 && sps_data[2] == 0 && sps_data[3] == 1) { // TODO: 00 00 00 01
- start_code_length = 4;
- } else if ((sps_data[0] & 0x1f) == 7) { // TODO: 继StartCode后第一个字节以 0x67 开头
- start_code_length = 0;
- } else {
- return false;
- }
- sps_data += start_code_length;
- sps_size -= start_code_length;
-
- /// 标准文档里注明: SPS、PPS、SEI的解析,基于RBSP语法
- /// ITU-T Advanced Video Coding For Generic Audiovisual Services
- std::vector<uint8_t> rbsp = EBSP2RBSP(sps_data, (int)sps_size);
- bs_t *b = bs_new(rbsp.data(), rbsp.size());
-
- /// Nalu Header
- uint32_t forbidden_zero_bit = bs_read_u(b, 1);
- uint32_t nal_ref_idc = bs_read_u(b, 2);
- uint32_t nal_unit_type = bs_read_u(b, 5);
-
- NaluHeader nalu_header;
- nalu_header.nal_ref_idc = nal_ref_idc;
- nalu_header.nal_unit_type = nal_unit_type;
-
- /// 序列参数集(SPS)-RBSP语法
- if (H264_NAL_SPS == (NAL_TYPE)nal_unit_type) {
- memset(&sps, 0, sizeof(NaluSPS));
- sps.profile_idc = bs_read_u8(b); // TODO: 当前H.264的编码配置, baseline(66) | main(77) | extended(88)
-
- sps.constraint_set0_flag = bs_read_u(b, 1);
- sps.constraint_set1_flag = bs_read_u(b, 1);
- sps.constraint_set2_flag = bs_read_u(b, 1);
- sps.constraint_set3_flag = bs_read_u(b, 1);
- sps.constraint_set4_flag = bs_read_u(b, 1);
- sps.constraint_set5_flag = bs_read_u(b, 1);
-
- sps.reserved_zero_2bits = bs_read_u(b, 2);
- sps.level_idc = bs_read_u8(b);
- sps.seq_parameter_set_id = bs_read_ue(b);
-
- if (sps.profile_idc == 100 || sps.profile_idc == 110 || sps.profile_idc == 122 || sps.profile_idc == 244 || sps.profile_idc == 44 ||
- sps.profile_idc == 83 || sps.profile_idc == 86 || sps.profile_idc == 118 || sps.profile_idc == 128 || sps.profile_idc == 138) {
-
- sps.chroma_format_idc = bs_read_ue(b);
- if (sps.chroma_format_idc == 3) {
- sps.residual_colour_transform_flag = bs_read_u(b, 1);
- }
-
- sps.bit_depth_luma_minus8 = bs_read_ue(b);
- sps.bit_depth_chroma_minus8 = bs_read_ue(b);
- sps.qpprime_y_zero_transform_bypass_flag = bs_read_u(b, 1);
- sps.seq_scaling_matrix_present_flag = bs_read_u(b, 1);
-
- if (sps.seq_scaling_matrix_present_flag) {
- uint32_t *ScalingList4x4[12];
- uint32_t UseDefaultScalingMatrix4x4Flag[12];
- uint32_t *ScalingList8x8[12];
- uint32_t UseDefaultScalingMatrix8x8Flag[12];
- for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 8 : 12); i++) {
- sps.seq_scaling_list_present_flag[i] = bs_read_u(b, 1);
- if (sps.seq_scaling_list_present_flag[i]) {
- if (i < 6) {
- scaling_list(b, ScalingList4x4[i], 16, UseDefaultScalingMatrix4x4Flag[i]);
- } else {
- scaling_list(b, ScalingList8x8[i - 6], 64, UseDefaultScalingMatrix8x8Flag[i - 6]);
- }
- }
- }
- }
- }
-
- sps.log2_max_frame_num_minus4 = bs_read_ue(b);
- sps.pic_order_cnt_type = bs_read_ue(b);
-
- if (sps.pic_order_cnt_type == 0) {
- sps.log2_max_pic_order_cnt_lsb_minus4 = bs_read_ue(b);
- } else if (sps.pic_order_cnt_type == 1) {
- sps.delta_pic_order_always_zero_flag = bs_read_u(b, 1);
- sps.offset_for_non_ref_pic = bs_read_se(b);
- sps.offset_for_top_to_bottom_field = bs_read_se(b);
- sps.num_ref_frames_in_pic_order_cnt_cycle = bs_read_ue(b);
- for (int i = 0; i < sps.num_ref_frames_in_pic_order_cnt_cycle; i++) {
- sps.offset_for_ref_frame[i] = bs_read_se(b);
- }
- }
-
- sps.max_num_ref_frames = bs_read_ue(b); // TODO: 参考帧的最大数目
- sps.gaps_in_frame_num_value_allowed_flag = bs_read_u(b, 1);
- sps.pic_width_in_mbs_minus1 = bs_read_ue(b); // TODO: 用于计算图像的宽度,单位为宏块个数
- sps.pic_height_in_map_units_minus1 = bs_read_ue(b); // TODO: 度量视频中一帧图像的高度
- uint32_t width = (sps.pic_width_in_mbs_minus1 + 1) * 16;
- uint32_t height = (sps.pic_height_in_map_units_minus1 + 1) * 16;
- sps.frame_mbs_only_flag = bs_read_u(b, 1); // TODO: 宏块的编码方式
-
- if (!sps.frame_mbs_only_flag) {
- sps.mb_adaptive_frame_field_flag = bs_read_u(b, 1);
- }
-
- sps.direct_8x8_inference_flag = bs_read_u(b, 1);
- sps.frame_cropping_flag = bs_read_u(b, 1);
-
- if (sps.frame_cropping_flag) {
- sps.frame_crop_left_offset = bs_read_ue(b);
- sps.frame_crop_right_offset = bs_read_ue(b);
- sps.frame_crop_top_offset = bs_read_ue(b);
- sps.frame_crop_bottom_offset = bs_read_ue(b);
- }
-
- sps.vui_parameters_present_flag = bs_read_u(b, 1); // TODO: SPS中是否存在VUI信息?
- if (sps.vui_parameters_present_flag) {
- vui_parameters(b, sps);
- }
-
- rbsp_trailing_bits(b);
- }
-
- bs_free(b);
- return true;
- }
vui_parameters 是视频编码中的一种参数,用于描述视频序列的附加信息,即视频使用者信息 (Video Usability Information)。vui_parameters 包含了与视频序列的使用和显示相关的配置信息,以提供更好的用户体验和兼容性。
vui_parameters 主要包括以下信息:
- // Vui Parameters
- typedef struct {
- uint32_t aspect_ratio_info_present_flag;
- // if(aspect_ratio_info_present_flag) {
- uint32_t aspect_ratio_idc;
- // if (aspect_ratio_idc == Extended_SAR) {
- uint32_t sar_width;
- uint32_t sar_height;
- // }
- // }
- uint32_t overscan_info_present_flag;
- // if (overscan_info_present_flag) {
- uint32_t overscan_appropriate_flag;
- // }
- uint32_t video_signal_type_present_flag;
- // if (video_signal_type_present_flag) {
- uint32_t video_format;
- uint32_t video_full_range_flag;
- uint32_t colour_description_present_flag;
- // if (colour_description_present_flag) {
- uint32_t colour_primaries;
- uint32_t transfer_characteristics;
- uint32_t matrix_coefficients;
- // }
- // }
- uint32_t chroma_loc_info_present_flag;
- // if (chroma_loc_info_present_flag) {
- uint32_t chroma_sample_loc_type_top_field;
- uint32_t chroma_sample_loc_type_bottom_field;
- // }
- uint32_t timing_info_present_flag;
- // if (timing_info_present_flag) {
- uint32_t num_units_in_tick;
- uint32_t time_scale;
- uint32_t fixed_frame_rate_flag;
- // }
- uint32_t nal_hrd_parameters_present_flag;
- // if (nal_hrd_parameters_present_flag) {
- NaluSpsHrdParameters nal_hrd_parameters_present;
- // }
- uint32_t vcl_hrd_parameters_present_flag;
- // if (vcl_hrd_parameters_present_flag) {
- NaluSpsHrdParameters vcl_hrd_parameters_present;
- // }
- // if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
- uint32_t low_delay_hrd_flag;
- // }
- uint32_t pic_struct_present_flag;
- uint32_t bitstream_restriction_flag;
- // if (bitstream_restriction_flag) {
- uint32_t motion_vectors_over_pic_boundaries_flag;
- uint32_t max_bytes_per_pic_denom;
- uint32_t max_bits_per_mb_denom;
- uint32_t log2_max_mv_length_horizontal;
- uint32_t log2_max_mv_length_vertical;
- uint32_t num_reorder_frames;
- uint32_t max_dec_frame_buffering;
- // }
- } NaluSpsVuiParameters;
- void vui_parameters(bs_t *b, NaluSPS &sps) {
- NaluSpsVuiParameters vui;
- memset(&vui, 0, sizeof(NaluSpsVuiParameters));
-
- vui.aspect_ratio_info_present_flag = bs_read_u1(b);
- if (vui.aspect_ratio_info_present_flag) {
- vui.aspect_ratio_idc = bs_read_u8(b);
- if (vui.aspect_ratio_idc == 255) {
- vui.sar_width = bs_read_u(b, 16);
- vui.sar_height = bs_read_u(b, 16);
- }
- }
-
- vui.overscan_info_present_flag = bs_read_u1(b);
- if (vui.overscan_info_present_flag) {
- vui.overscan_appropriate_flag = bs_read_u1(b);
- }
-
- vui.video_signal_type_present_flag = bs_read_u1(b);
- if (vui.video_signal_type_present_flag) {
- vui.video_format = bs_read_u(b, 3);
- vui.video_full_range_flag = bs_read_u1(b);
-
- vui.colour_description_present_flag = bs_read_u1(b);
- if (vui.colour_description_present_flag) {
- vui.colour_primaries = bs_read_u8(b);
- vui.transfer_characteristics = bs_read_u8(b);
- vui.matrix_coefficients = bs_read_u8(b);
- }
- }
-
- vui.chroma_loc_info_present_flag = bs_read_u1(b);
- if (vui.chroma_loc_info_present_flag) {
- vui.chroma_sample_loc_type_top_field = bs_read_ue(b);
- vui.chroma_sample_loc_type_bottom_field = bs_read_ue(b);
- }
-
- vui.timing_info_present_flag = bs_read_u1(b);
- if (vui.timing_info_present_flag) {
- vui.num_units_in_tick = bs_read_u(b, 32);
- vui.time_scale = bs_read_u(b, 32);
- vui.fixed_frame_rate_flag = bs_read_u1(b);
- }
-
- vui.nal_hrd_parameters_present_flag = bs_read_u1(b);
- if (vui.nal_hrd_parameters_present_flag) {
- hrd_parameters(b);
- }
-
- vui.vcl_hrd_parameters_present_flag = bs_read_u1(b);
- if (vui.vcl_hrd_parameters_present_flag) {
- hrd_parameters(b);
- }
-
- if (vui.nal_hrd_parameters_present_flag || vui.vcl_hrd_parameters_present_flag) {
- vui.low_delay_hrd_flag = bs_read_u1(b);
- }
-
- vui.pic_struct_present_flag = bs_read_u1(b);
-
- vui.bitstream_restriction_flag = bs_read_u1(b);
- if (vui.bitstream_restriction_flag) {
- vui.motion_vectors_over_pic_boundaries_flag = bs_read_u1(b);
- vui.max_bytes_per_pic_denom = bs_read_ue(b);
- vui.max_bits_per_mb_denom = bs_read_ue(b);
- vui.log2_max_mv_length_horizontal = bs_read_ue(b);
- vui.log2_max_mv_length_vertical = bs_read_ue(b);
- vui.num_reorder_frames = bs_read_ue(b);
- vui.max_dec_frame_buffering = bs_read_ue(b);
- }
-
- sps.vui_parameters = vui;
- }
hrd_parameters 是视频编码中的一种参数,用于描述视频编码的恢复点检测相关的信息。HRD 是 Hypothetical Reference Decoder(假设参考解码器)的缩写,它定义了视频编码的比特率、缓冲区大小和相关的时间参数。
hrd_parameters 包含了视频编码过程中的控制和管理参数,用于确保编码后的视频流在解码时能够正确恢复,并保持一定的稳定性和适应性。
hrd_parameters 主要包括以下信息:
- typedef struct {
- uint32_t cpb_cnt_minus1;
- uint32_t bit_rate_scale;
- uint32_t cpb_size_scale;
- // for( SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++ ) {
- uint32_t bit_rate_value_minus1[5];
- uint32_t cpb_size_value_minus1[5];
- uint32_t cbr_flag[5];
- // }
- uint32_t initial_cpb_removal_delay_length_minus1;
- uint32_t cpb_removal_delay_length_minus1;
- uint32_t dpb_output_delay_length_minus1;
- uint32_t time_offset_length;
- } NaluSpsHrdParameters;
- void hrd_parameters(bs_t *b, NaluSpsHrdParameters &out_hrd) {
- NaluSpsHrdParameters hrd;
- memset(&hrd, 0, sizeof(NaluSpsHrdParameters));
-
- hrd.cpb_cnt_minus1 = bs_read_ue(b);
- hrd.bit_rate_scale = bs_read_u(b, 4);
- hrd.cpb_size_scale = bs_read_u(b, 4);
-
- for (int SchedSelIdx = 0; SchedSelIdx <= hrd.cpb_cnt_minus1; SchedSelIdx++) {
- hrd.bit_rate_value_minus1[SchedSelIdx] = bs_read_ue(b);
- hrd.cpb_size_value_minus1[SchedSelIdx] = bs_read_ue(b);
- hrd.cbr_flag[SchedSelIdx] = bs_read_u1(b);
- }
- hrd.initial_cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
- hrd.cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
- hrd.dpb_output_delay_length_minus1 = bs_read_u(b, 5);
- hrd.time_offset_length = bs_read_u(b, 5);
- }
- /// 缩放比例列表
- void scaling_list(bs_t *b, uint32_t *scalingList, int sizeOfScalingList, uint32_t useDefaultScalingMatrixFlag) {
- int lastScale = 8;
- int nextScale = 8;
- for (int j = 0; j < sizeOfScalingList; j++) {
- if (nextScale != 0) {
- //!< delta_scale
- int32_t delta_scale = bs_read_se(b);
- nextScale = (lastScale + delta_scale + 256) % 256;
- useDefaultScalingMatrixFlag = (j == 0 && nextScale == 0);
- }
- scalingList[j] = (nextScale == 0) ? lastScale : nextScale;
- lastScale = (int)scalingList[j];
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。