Recently Learning HEVC, refer to H264bitstream Open Source Library to re-write code parsing stream. When observing the analysis results of H264 streams, it was found that the results of this library analysis were somewhat different from those of commercial tools. Also encountered before, but also wrote an article, "A Bug to solve H264bitstream", after debugging found that the H264bitstream library implementation of some small problems, so modify the changes to form this article.
First, the header file
1. Renaming and new addition
Rename the Residual_colour_transform_flag of the sps_t structure to Separate_colour_plane_flag. According to the latest document, sps_t structure new add Chromaarraytype. Add colour_plane_id members to the slice_header_t structure.
2. New addition vector
Remove the extern "C" limit and add the STD vector.
#include <vector>
Using Std::vector;
3. Partial structure separation
Separate the PWT, RPLR, and drpm of the slice_header_t structure. Because the number of these fields is not fixed, vector storage is used and the code is as follows:
Predictive weight table typedef struct {int luma_log2_weight_denom;
int chroma_log2_weight_denom;
int luma_weight_l0_flag[64];
int luma_weight_l0[64];
int luma_offset_l0[64];
int chroma_weight_l0_flag[64];
int chroma_weight_l0[64][2];
int chroma_offset_l0[64][2];
int luma_weight_l1_flag[64];
int luma_weight_l1[64];
int luma_offset_l1[64];
int chroma_weight_l1_flag[64];
int chroma_weight_l1[64][2];
int chroma_offset_l1[64][2];
} pwt_t;
Ref pic List modification typedef struct {int MODIFICATION_OF_PIC_NUMS_IDC;
int Abs_diff_pic_num_minus1;
int long_term_pic_num;
} Rplm_tt;
typedef struct {int ref_pic_list_modification_flag_l0;
int ref_pic_list_modification_flag_l1;
Vector<rplm_tt> RPLM;
} rplm_t;
Decoded ref pic marking typedef struct {int memory_management_control_operation;
int Difference_of_pic_nums_minus1;
int long_term_pic_num;
int long_term_frame_idx; int max_lOng_term_frame_idx_plus1;
} Drpm_tt;
typedef struct {int no_output_of_prior_pics_flag;
int Long_term_reference_flag;
int Adaptive_ref_pic_marking_mode_flag;
Vector<drpm_tt> drpm; } drpm_t;
slice_header_t the corresponding changes are as follows:
pwt_t PWT;
rplm_t RPLM;
Drpm_t drpm;
II. implementation of the document
1, rename the read_ref_pic_list_reordering function to read_ref_pic_list_modification. Added to the vector according to different values. The implementation changes are as follows:
7.3.3.1 Reference Picture List modification syntax void read_ref_pic_list_modification (h264_stream_t* h, bs_t* b) {
slice_header_t* sh = h->sh;
Rplm_tt RPLMTT; if (! Is_slice_type (Sh->slice_type, sh_slice_type_i) &&! Is_slice_type (Sh->slice_type, SH_SLICE_TYPE_
SI) {sh->rplm.ref_pic_list_modification_flag_l0 = BS_READ_U1 (b); if (sh->rplm.ref_pic_list_modification_flag_l0) {do {Rplmtt.modifica
TION_OF_PIC_NUMS_IDC = Bs_read_ue (b);
if (RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC = = 0 | | RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC = = 1) {Rplmtt.abs_diff_pic_num_minus1 = Bs_read_
UE (b); } else if (RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC = = 2) {Rplmtt.long_te
Rm_pic_num = Bs_read_ue (b);
} sh->rplm.rplm.push_back (RPLMTT); } while (RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC! = 3 &&! bs_eof (b)); }} if (Is_slice_type (Sh->slice_type, Sh_slice_type_b)) {Sh->rplm.ref_pic_list_modification_
FLAG_L1 = BS_READ_U1 (b); if (SH->RPLM.REF_PIC_LIST_MODIFICATION_FLAG_L1) {do {Rplmtt.modifica
TION_OF_PIC_NUMS_IDC = Bs_read_ue (b);
if (RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC = = 0 | | RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC = = 1) {Rplmtt.abs_diff_pic_num_minus1 = Bs_read_
UE (b); } else if (RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC = = 2) {Rplmtt.long_te
Rm_pic_num = Bs_read_ue (b);
} sh->rplm.rplm.push_back (RPLMTT);
} while (RPLMTT.MODIFICATION_OF_PIC_NUMS_IDC! = 3 &&! bs_eof (b)); }
}
}
2. Similar to above, the read_dec_ref_pic_marking function is changed as follows:
7.3.3.3 decoded reference picture marking syntax void read_dec_ref_pic_marking (h264_stream_t* h, bs_t* b) {slice_he
ader_t* sh = h->sh;
Drpm_tt DRPMTT;
if (H->nal->nal_unit_type = = 5) {Sh->drpm.no_output_of_prior_pics_flag = BS_READ_U1 (b);
Sh->drpm.long_term_reference_flag = BS_READ_U1 (b);
} else {sh->drpm.adaptive_ref_pic_marking_mode_flag = BS_READ_U1 (b); if (Sh->drpm.adaptive_ref_pic_marking_mode_flag) {do {Drpmtt.memory_
Management_control_operation = Bs_read_ue (b);
if (drpmtt.memory_management_control_operation = = 1 | | Drpmtt.memory_management_control_operation = = 3) {Drpmtt.difference_of_pic_nums_minu
S1 = Bs_read_ue (b); } if (drpmtt.memory_management_control_operation = = 2) {drpmtt.long_t Erm_pic_num = Bs_Read_ue (b);
} if (drpmtt.memory_management_control_operation = = 3 | | Drpmtt.memory_management_control_operation = = 6) {Drpmtt.long_term_frame_idx = Bs_re
Ad_ue (b); } if (drpmtt.memory_management_control_operation = = 4) {drpmtt.max_l
Ong_term_frame_idx_plus1 = Bs_read_ue (b);
} sh->drpm.drpm.push_back (DRPMTT);
} while (drpmtt.memory_management_control_operation! = 0 &&! bs_eof (b)); }
}
}
3. The num_ref_idx_l0_active_minus1 used in the Read_pred_weight_table function is the pps_t structure, which is wrong. It is correct to use the num_ref_idx_l0_active_minus1 of the slice_header_t structure.
for (i = 0; I <= pps->num_ref_idx_l0_active_minus1; i++)
To change to
for (i = 0; I <= sh->num_ref_idx_l0_active_minus1; i++)
Other minor changes are not listed in this article. Source code See GitHub repository: Https://github.com/latelee/H264BSAnalyzer's Branch_dev branch. Specific as follows:
Https://github.com/latelee/H264BSAnalyzer/blob/Branch_dev/H264BSAnalyzer/h264_stream.h
Https://github.com/latelee/H264BSAnalyzer/blob/Branch_dev/H264BSAnalyzer/h264_stream.cpp
Li Yu 2015.9.28 Night