理論知識參考
十一、H.264的Slice Header解析
1、理論依據
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPR10dJRVT5tmeOpHOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1UDO5AjNwADM0EDNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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解析之間的互動