【H264解析Demo】7、解析Slice Header

理论知识参考
十一、H.264的Slice Header解析

1、理论依据

在这里插入图片描述在这里插入图片描述

2、类定义

slice头部

//解析slice头部
class CSliceHeader
{
public:
	CSliceHeader(UINT8	*pSODB, CSeqParamSet *sps, CPicParamSet *pps, UINT8	nalType);
	~CSliceHeader();

	UINT32 Parse_slice_header();	//解析slice头部

	int	   m_disable_deblocking_filter_idc;
	int    m_slice_alpha_c0_offset;
	int    m_slice_beta_offset;
private:
	CSeqParamSet *m_sps_active;
	CPicParamSet *m_pps_active;
	UINT8	*m_pSODB;
	UINT8   m_nalType;
	/* slice头信息*/
	UINT16 m_first_mb_in_slice;		//当前slice中包含的第一个宏块在整帧中的位置
	UINT8  m_slice_type;	//当前slice的类型
	UINT8  m_pps_id;		//slice所依赖的pps的id
	UINT8  m_colour_plane_id;	//表示当前的颜色分量,0、1、2分别表示Y、U、V分量
	UINT32 m_frame_num;		//表示当前帧序号的一种计量方式
	bool   m_field_pic_flag;	//场编码标识位
	bool   m_bottom_field_flag;	//底场标识位
	UINT16 m_idr_pic_id;	//表示IDR帧的序号
	UINT32 m_poc;	//表示当前帧序号的另一种计量方式
	int	   m_delta_poc_bottom;	// 表示顶场与底场POC差值的计算方法,不存在则默认为0
	DecRefPicMarking m_dec_ref_pic_marking;
	int	   m_slice_qp_delta;	// 用于计算 当前slice内所使用的初始qp
};

slice整体

class CSliceStruct
{
public:
	CSliceStruct(UINT8	*pSODB, CSeqParamSet *sps, CPicParamSet *pps, UINT8	nalType, UINT32 sliceIdx);
	~CSliceStruct();

	CSliceHeader *m_sliceHeader;

	int Parse();

	CSeqParamSet *m_sps_active;	//解析所依赖的序列参数集SPS
	CPicParamSet *m_pps_active;	//解析所依赖的图像参数集PPS

private:
	UINT8	*m_pSODB;
	UINT8   m_nalType;		//是否为IDR
	UINT32  m_sliceIdx;

	UINT16 m_max_mb_number;
};

3、slice解析

解析slice头

UINT32 CSliceHeader::Parse_slice_header()
{
	UINT32 sliceHeaderLengthInBits = 0;	//sliceHeader占据了整个slice多长的bit
	UINT8  bitPosition = 0;
	UINT32 bytePosition = 0;

	m_first_mb_in_slice = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);
	m_slice_type = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);
	m_slice_type %= 5;
	m_pps_id = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);

	if (m_sps_active->Get_separate_colour_plane_flag())	/* 根据协议,需要根据sps中的字段来决定 */
	{
		m_colour_plane_id = Get_uint_code_num(m_pSODB, bytePosition, bitPosition, 2);
	}

	m_frame_num = Get_uint_code_num(m_pSODB, bytePosition, bitPosition, m_sps_active->Get_log2_max_frame_num());

	if (!m_sps_active->Get_frame_mbs_only_flag())	/*  是否仅为帧编码 */
	{
		m_field_pic_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);	/* 获取场编码标志位 */
		if (m_field_pic_flag)
		{
			m_bottom_field_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);
		}
	}

	if (m_nalType == 5)		/* 如果是IDR帧才获取IDR帧的序号 */
	{
		m_idr_pic_id = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);
	}

	if (m_sps_active->Get_poc_type() == 0)
	{
		m_poc = Get_uint_code_num(m_pSODB, bytePosition, bitPosition, m_sps_active->Get_log2_max_poc_cnt());	/* 根绝POC最大长度来获取 */
		if ((!m_field_pic_flag) && m_pps_active->Get_bottom_field_pic_order_in_frame_present_flag())
		{
			m_delta_poc_bottom = Get_sev_code_num(m_pSODB, bytePosition, bitPosition);
		}
	}
	
	if (m_nalType == 5)
	{
		m_dec_ref_pic_marking.no_output_of_prior_pics_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);
		m_dec_ref_pic_marking.long_term_reference_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);
	}

	m_slice_qp_delta = Get_sev_code_num(m_pSODB, bytePosition, bitPosition);
	
	if (m_pps_active->Get_deblocking_filter_control_present_flag())
	{
		m_disable_deblocking_filter_idc = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);
		if (m_disable_deblocking_filter_idc != 1)
		{
			m_slice_alpha_c0_offset = 2 * Get_sev_code_num(m_pSODB, bytePosition, bitPosition);
			m_slice_beta_offset = 2 * Get_sev_code_num(m_pSODB, bytePosition, bitPosition);
		}
	}

	sliceHeaderLengthInBits = 8 * bytePosition + bitPosition;

	return sliceHeaderLengthInBits;
}

解析slice整体

int CSliceStruct::Parse()
{
	UINT32 sliceHeaderLength = 0;
	m_sliceHeader = new CSliceHeader(m_pSODB, m_sps_active, m_pps_active, m_nalType);
	sliceHeaderLength = m_sliceHeader->Parse_slice_header();	//返回sliceHeader占用的位数,方便解析slice内容
	
	/* 后面开始解析一个个的宏块 */
	
	return kPARSING_ERROR_NO_ERROR;
}

总结

本节重点需要了解的是slice的解析是用到sps中的成员的,体会sps和slice解析之间的交互

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值