【H264解析Demo】8、解析Slice Body、宏块解析

一、标准文档解析

1、macroblock_layer解析

1、获取宏块类型
2、判断宏块类型:区分I_PCM、1616、NN(本节解析NN)
3、n
n所以执行到序号2
4、判断pps中填充的非88并且宏块类型是NN:解析mb_pred,宏块预测
5、判断宏块类型非16*16,则获取m_coded_block_pattern
6、if (m_cbp_luma > 0 || m_cbp_chroma > 0 || (m_mb_type > 0 && m_mb_type < 25))则获取QP值,m_cbp_luma和m_cbp_chroma是coded_block_pattern根据协议文档计算得出的
在这里插入图片描述

2、mb_pred解析

1、判断是帧内44还是帧内88,分别获取每个子块的预测模式
2、获取帧内色度预测模式
在这里插入图片描述

二、计算宏块个数

//宽(图像以宏块为单位的宽度)*高,数据保存在图片参数集中
m_max_mb_number = m_sps_active->Get_pic_width_in_mbs() * m_sps_active->Get_pic_height_in_mbs();	

三、计算QP值

三者之和:pps中qp初值+slice header中qp值+宏块中的qp值

m_mb_qp_delta = Get_sev_code_num(m_pSODB, m_bypeOffset, m_bitOffset);
m_mb_qp = m_pps_active->Get_pic_init_qp() + m_slice->m_sliceHeader->Get_slice_qp_delta() + m_mb_qp_delta;

四、宏块结构数据定义

// 预测模式结构
typedef struct Intrleft_diff2_negativeredStruct
{
	UINT8 block_mode;	//block_mode : 0 - 4x4 mode; 1 - 8x8 mode;
	bool prev_intra_pred_mode_flag;
	UINT8 rem_intra_pred_mode;

	Intrleft_diff2_negativeredStruct()
	{
		block_mode = 0;
		prev_intra_pred_mode_flag = false;
		rem_intra_pred_mode = 0;
	}
} Intrleft_diff2_negativeredStruct;

// 宏块类
class CMacroblock
{
public:
	CMacroblock(UINT8 *pSODB, UINT32 offset, int idx);	//offset当前宏块在地址中的偏移量
	virtual ~CMacroblock();

	UINT8  m_mb_type;

private:
	UINT8  *m_pSODB;
	UINT32  m_bypeOffset;	//字节的偏移量
	UINT8  m_bitOffset;		//bit的偏移量

	bool   m_transform_size_8x8_flag;	//当该标识位为1时,预测残差按照8×8像素块进行解码;当该标志位不存在或者为0时,预测残差按照4×4像素块进行解码

	Intrleft_diff2_negativeredStruct *m_pred_struct;	//mb_pred宏块预测语法定义
	UINT8  m_intra_chroma_pred_mode;	//表示色度分量的帧内预测模式

	UINT8  m_coded_block_pattern;	//用于表示当前宏块内的4个8×8子块编码对其中的哪个的残差系数进行编码
	UINT8  m_mb_qp_delta;		//计算当前宏块的量化参数偏移量的值
};

五、宏块解析

UINT32 CMacroblock::Parse_macroblock()		//对应协议macroblock_layer
{
	UINT32 residualLength = 0;
	m_mb_type = Get_uev_code_num(m_pSODB, m_bypeOffset, m_bitOffset);

	if (m_mb_type == 25)
	{
		// To do: I-PCM mode...
	} 
	else if (m_mb_type == 0)		//对应mb_pred的解析
	{
		// Intra_NxN mode...
		if (m_pps_active->Get_transform_8x8_mode_flag())	//
		{
			m_transform_size_8x8_flag = Get_bit_at_position(m_pSODB, m_bypeOffset, m_bitOffset);
		}

		// Get prediction-block num...
		if (m_transform_size_8x8_flag)
		{
			// Using intra_8x8
			m_pred_struct = new Intrleft_diff2_negativeredStruct[4];	
			for (int luma8x8BlkIdx = 0; luma8x8BlkIdx < 4; luma8x8BlkIdx++)
			{
				m_pred_struct[luma8x8BlkIdx].block_mode = 1;
				m_pred_struct[luma8x8BlkIdx].prev_intra_pred_mode_flag = Get_bit_at_position(m_pSODB, m_bypeOffset, m_bitOffset);
				if (!m_pred_struct[luma8x8BlkIdx].prev_intra_pred_mode_flag)
				{
					m_pred_struct[luma8x8BlkIdx].rem_intra_pred_mode = Get_uint_code_num(m_pSODB, m_bypeOffset, m_bitOffset, 3);
				}
			}
		} 
		else
		{
			// Using intra_4x4
			m_pred_struct = new Intrleft_diff2_negativeredStruct[16];
			for (int luma4x4BlkIdx = 0; luma4x4BlkIdx < 16; luma4x4BlkIdx++)
			{
				m_pred_struct[luma4x4BlkIdx].block_mode = 0;
				m_pred_struct[luma4x4BlkIdx].prev_intra_pred_mode_flag = Get_bit_at_position(m_pSODB, m_bypeOffset, m_bitOffset);
				if (!m_pred_struct[luma4x4BlkIdx].prev_intra_pred_mode_flag)
				{
					m_pred_struct[luma4x4BlkIdx].rem_intra_pred_mode = Get_uint_code_num(m_pSODB, m_bypeOffset, m_bitOffset, 3);
				}
			}
		}

		// intra_chroma_pred_mode
		m_intra_chroma_pred_mode = Get_uev_code_num(m_pSODB, m_bypeOffset, m_bitOffset);
	}
	else
	{
		// To do: Intra_16x16 mode
		m_intra16x16PredMode = (m_mb_type - 1) % 4;
		m_cbp_luma = (m_mb_type <= 12) ? 0 : 15;
		m_cbp_chroma = ((m_mb_type - 1) / 4) % 3;

		// intra_chroma_pred_mode
		m_intra_chroma_pred_mode = Get_uev_code_num(m_pSODB, m_bypeOffset, m_bitOffset);
	}

	if (m_mb_type == 0 || m_mb_type == 25)
	{
		m_coded_block_pattern = Get_me_code_num(m_pSODB, m_bypeOffset, m_bitOffset, 1);		//映射指数哥伦布编码
		m_cbp_luma = m_coded_block_pattern % 16;
		m_cbp_chroma = m_coded_block_pattern / 16;
	}
	
	if (m_cbp_luma > 0 || m_cbp_chroma > 0 || (m_mb_type > 0 && m_mb_type < 25))
	{
		m_mb_qp_delta = Get_sev_code_num(m_pSODB, m_bypeOffset, m_bitOffset);
		m_mb_qp = m_pps_active->Get_pic_init_qp() + m_slice->m_sliceHeader->Get_slice_qp_delta() + m_mb_qp_delta;
	}
	
	/* 标注文档中:residual( 0, 15 )
	  *后半部分的预测残差数据的解析需要依赖学习了CAVLC和CABAC之后才能继续,先保留 
	  */

	m_mbDataSize = m_bypeOffset * 8 + m_bitOffset - m_mbDataSize;
	return m_mbDataSize;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值