一、标准文档解析
1、macroblock_layer解析
1、获取宏块类型
2、判断宏块类型:区分I_PCM、1616、NN(本节解析NN)
3、nn所以执行到序号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;
}