H.264 片段头(SliceHead)

基本结构(SliceHead)

H.264(也称为 AVC)是一种视频编码标准,它将视频帧分割成多个片段进行压缩。每个片段称为 Slice,SliceHeader 是 H.264 中用于描述每个片段的结构。

SliceHeader 结构包含了以下一些重要信息:

  1. first_mb_in_slice:表示当前 Slice 中的第一个宏块(Macroblock)在整个图像中的索引。
  2. slice_type:表示 Slice 的类型,如 I 帧(Intra Frame)、P 帧(Predictive Frame)或 B 帧(Bi-Directional Predictive Frame)。
  3. pic_parameter_set_id:指示当前 Slice 使用的图像参数集(Picture Parameter Set)的索引。
  4. frame_num:表示当前 Slice 所属的帧的帧号。
  5. idr_pic_id:在 IDR 图像(Instantaneous Decoder Refresh)中,表示当前 Slice 所属的 IDR 图像的图像标识符。
  6. pic_order_cnt_lsb:表示当前 Slice 的图像顺序计数器的最低有效位。
  7. slice_qp_delta:表示当前 Slice 的量化参数偏移量,用于控制编码的质量和压缩率。
  8. 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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕加索解锁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值