大家好,欢迎来到IT知识分享网。
基本结构(SliceHead)
H.264(也称为 AVC)是一种视频编码标准,它将视频帧分割成多个片段进行压缩。每个片段称为 Slice,SliceHeader 是 H.264 中用于描述每个片段的结构。
SliceHeader 结构包含了以下一些重要信息:
- first_mb_in_slice:表示当前 Slice 中的第一个宏块(Macroblock)在整个图像中的索引。
- slice_type:表示 Slice 的类型,如 I 帧(Intra Frame)、P 帧(Predictive Frame)或 B 帧(Bi-Directional Predictive Frame)。
- pic_parameter_set_id:指示当前 Slice 使用的图像参数集(Picture Parameter Set)的索引。
- frame_num:表示当前 Slice 所属的帧的帧号。
- idr_pic_id:在 IDR 图像(Instantaneous Decoder Refresh)中,表示当前 Slice 所属的 IDR 图像的图像标识符。
- pic_order_cnt_lsb:表示当前 Slice 的图像顺序计数器的最低有效位。
- slice_qp_delta:表示当前 Slice 的量化参数偏移量,用于控制编码的质量和压缩率。
- disable_deblocking_filter_idc:表示是否禁用去块滤波器,用于平滑边缘和减少压缩伪影。
slice_header()
封装结构
// SliceHeader typedef struct { uint32_t first_mb_in_slice; uint32_t slice_type; uint32_t pic_parameter_set_id; uint32_t frame_num; // if (!frame_mbs_only_flag) { uint32_t field_pic_flag; // if (field_pic_flag) { uint32_t bottom_field_flag; // } // } // if (nal_unit_type == 5) { uint32_t idr_pic_id; // } // if (pic_order_cnt_type == 0) { uint32_t pic_order_cnt_lsb; // if (pic_order_present_flag && !field_pic_flag) int delta_pic_order_cnt_bottom; // } // } // if (pic_order_cnt_type == 1 && !delta_pic_order_always_zero_flag) { int delta_pic_order_cnt[2]; // } // if (redundant_pic_cnt_present_flag) { uint32_t redundant_pic_cnt; // } // if (slice_type == B) { uint32_t direct_spatial_mv_pred_flag; // } // if (slice_type == P || slice_type == SP || slice_type == B ) { uint32_t num_ref_idx_active_override_flag; // if (num_ref_idx_active_override_flag) { uint32_t num_ref_idx_l0_active_minus1; uint32_t num_ref_idx_l1_active_minus1; // } // } NaluSliceRefPicListReordering ref_pic_list_reordering; // if ((weighted_pred_flag && (slice_type == P || slice_type == SP) || (weighted_bipred_idc == 1 && slice_type == B)) { NaluSlicePredWeightTable pred_weight_table; // } // if ( nal_ref_idc != 0) { NaluSliceDecrefPicMarking dec_ref_pic_marking; // } // if (entropy_coding_mode_flag && slice_type != I && slice_type != SI) { uint32_t cabac_init_idc; // } int slice_qp_delta; // if (slice_type == SP || slice_type == SI) { // if (slice_type == SP) uint32_t sp_for_switch_flag; int slice_qs_delta; // } // if (deblocking_filter_control_present_flag) { uint32_t disable_deblocking_filter_idc; int slice_alpha_c0_offset_div2; int slice_beta_offset_div2; // } // } // if (num_slice_groups_minus1 > 0 && slice_group_map_type >= 3 && slice_group_map_type <= 5) { uint32_t slice_group_change_cycle; // } } NaluSliceHeader; typedef struct { // if (nal_unit_type == 5) { uint32_t no_output_of_prior_pics_flag; uint32_t long_term_reference_flag; // } else { uint32_t adaptive_ref_pic_marking_mode_flag; // if (adaptive_ref_pic_marking_mode_flag) { // do { uint32_t memory_management_control_operation; // if (memory_management_control_operation == 1 || // memory_management_control_operation == 3) { uint32_t difference_of_pic_nums_minus1; // } // if (memory_management_control_operation == 2) { uint32_t long_term_pic_num; // } // if (memory_management_control_operation == 3 || // memory_management_control_operation == 6) { uint32_t long_term_frame_idx; // } // if (memory_management_control_operation == 4) { uint32_t max_long_term_frame_idx_plus1; // } // } while (memory_management_control_operation != 0) // } } NaluSliceDecrefPicMarking; typedef struct { uint32_t luma_log2_weight_denom; // if (chroma_format_idc != 0) { uint32_t chroma_log2_weight_denom; // } // for (i = 0; i <= num_ref_idx_l0_active_minus1; i++) { uint32_t luma_weight_l0_flag; // if (luma_weight_l0_flag) { int luma_weight_l0[32]; int luma_offset_l0[32]; // } // if (chroma_format_idc != 0) { uint32_t chroma_weight_l0_flag; // if (chroma_weight_l0_flag) { int chroma_weight_l0[32][2]; int chroma_offset_l0[32][2]; // } // } // } // if (slice_type == B) { // for (i = 0; i <= num_ref_idx_l1_active_minus1; i++) { uint32_t luma_weight_l1_flag; // if (luma_weight_l1_flag) { int luma_weight_l1[32]; int luma_offset_l1[32]; // } // if (chroma_format_idc != 0) { uint32_t chroma_weight_l1_flag; // if (chroma_weight_l1_flag) int chroma_weight_l1[32][2]; int chroma_offset_l1[32][2]; // } // } // } // } } NaluSlicePredWeightTable; typedef struct { uint32_t reordering_of_pic_nums_idc; uint32_t ref_pic_list_reordering_flag_l0; uint32_t ref_pic_list_reordering_flag_l1; uint32_t abs_diff_pic_num_minus1; uint32_t long_term_pic_num; } NaluSliceRefPicListReordering;
解析过程
/// 解析切片头 bool parse_slice_header(uint8_t *slice_data, uint32_t slice_size, const NaluSPS &sps, const NaluPPS &pps, NaluSliceHeader &slice_header) { if (slice_size < 4) { return false; } /// 找到 SLICE NAL 单元的起始位置 int start_code_length = 0; if (slice_data[0] == 0 && slice_data[1] == 0 && slice_data[2] == 1) { // TODO: 00 00 01 start_code_length = 3; } else if (slice_data[0] == 0 && slice_data[1] == 0 && slice_data[2] == 0 && slice_data[3] == 1) { // TODO: 00 00 00 01 start_code_length = 4; } else if ((slice_data[0] & 0x1f) == 8) { // TODO: 继StartCode后第一个字节以 0x68 开头 start_code_length = 0; } else { return false; } slice_data += start_code_length; slice_size -= start_code_length; /// bit stream std::vector<uint8_t> rbsp = EBSP2RBSP(slice_data, (int)slice_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; /// SLICE if (H264_NAL_SLICE == (NAL_TYPE)nal_unit_type || // H264_NAL_IDR_SLICE == (NAL_TYPE)nal_unit_type) { memset(&slice_header, 0, sizeof(NaluSliceHeader)); slice_header.first_mb_in_slice = bs_read_ue(b); slice_header.slice_type = bs_read_ue(b); slice_header.pic_parameter_set_id = bs_read_ue(b); slice_header.frame_num = bs_read_u(b, (int)sps.log2_max_frame_num_minus4 + 4); if (!sps.frame_mbs_only_flag) { slice_header.field_pic_flag = bs_read_u1(b); if (slice_header.field_pic_flag) { slice_header.bottom_field_flag = bs_read_u1(b); } } if (nal_unit_type == 5) { slice_header.idr_pic_id = bs_read_ue(b); } if (sps.pic_order_cnt_type == 0) { slice_header.pic_order_cnt_lsb = bs_read_u(b, (int)sps.log2_max_pic_order_cnt_lsb_minus4 + 4); if (pps.pic_order_present_flag && !slice_header.field_pic_flag) { slice_header.delta_pic_order_cnt_bottom = bs_read_se(b); } } if (sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero_flag) { slice_header.delta_pic_order_cnt[0] = bs_read_se(b); if (pps.pic_order_present_flag && !slice_header.field_pic_flag) { slice_header.delta_pic_order_cnt[1] = bs_read_se(b); } } if (pps.redundant_pic_cnt_present_flag) { slice_header.redundant_pic_cnt = bs_read_ue(b); } std::string sSliceType = get_slice_type_str(slice_header.slice_type); if (sSliceType == "B") { slice_header.direct_spatial_mv_pred_flag = bs_read_u1(b); } if (sSliceType == "P" || sSliceType == "SP" || sSliceType == "B") { slice_header.num_ref_idx_active_override_flag = bs_read_u1(b); if (slice_header.num_ref_idx_active_override_flag) { slice_header.num_ref_idx_l0_active_minus1 = bs_read_ue(b); if (sSliceType == "B") { slice_header.num_ref_idx_l1_active_minus1 = bs_read_ue(b); } } } /// 参考图像列表重排序语法 ref_pic_list_reordering(b, slice_header); /// 预测加权表格语法 if ((pps.weighted_pred_flag && (sSliceType == "P" || sSliceType == "SP")) || (pps.weighted_bipred_idc == 1 && sSliceType == "B")) { pred_weight_table(b, sps, pps, slice_header); } /// 解码的参考图像标识语法 if (nal_ref_idc != 0) { dec_ref_pic_marking(b, slice_header, nal_unit_type); } if (pps.entropy_coding_mode_flag && sSliceType != "I" && sSliceType != "SI") { slice_header.cabac_init_idc = bs_read_ue(b); } slice_header.slice_qp_delta = bs_read_se(b); if (sSliceType == "SP" || sSliceType == "SI") { if (sSliceType == "SP") { slice_header.sp_for_switch_flag = bs_read_u1(b); slice_header.slice_qs_delta = bs_read_se(b); } if (pps.deblocking_filter_control_present_flag) { slice_header.disable_deblocking_filter_idc = bs_read_ue(b); if (slice_header.disable_deblocking_filter_idc != 1) { slice_header.slice_alpha_c0_offset_div2 = bs_read_se(b); slice_header.slice_beta_offset_div2 = bs_read_se(b); } } } if (pps.num_slice_groups_minus1 > 0 && pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5) { slice_header.slice_group_change_cycle = bs_read_u(b, ceil_log2((int)(pps.pic_size_in_map_units_minus1 / pps.slice_group_change_rate_minus1) + 1)); } } bs_free(b); return true; } int ceil_log2(int value) { double logValue = log2(value); int ceilValue = ceil(logValue); return ceilValue; }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/147056.html