关于h264bitstream的bug修正及完善
来源:互联网 发布:淘宝消费积分 编辑:程序博客网 时间:2024/05/22 12:28
最近学习HEVC,参考h264bitstream开源库重新写代码解析码流。在观察H264码流的分析结果时,发现该库分析的结果与商业工具有些不同。以前也遇到过,还写了篇文章《解决h264bitstream的一个bug》,经调试发现h264bitstream库实现上有些小问题,于是就修改修改,形成此文。
一、头文件
1、改名及新加
将sps_t结构体的residual_colour_transform_flag改名为separate_colour_plane_flag。根据最新文档,sps_t结构体新加ChromaArrayType。slice_header_t结构体添加colour_plane_id成员。
2、新加vector
去掉extern "C"的限制,添加std的vector。
#include <vector>
using std::vector;
3、分离部分结构体
将slice_header_t结构体的pwt、rplr和drpm独立出来。因为这些字段的数量不固定,使用了vector存储,代码如下:
// predictive weight tabletypedef 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 modificationtypedef 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 markingtypedef 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对应的变更如下:
pwt_t pwt;rplm_t rplm;drpm_t drpm;
二、实现文件
1、将read_ref_pic_list_reordering函数改名为read_ref_pic_list_modification。根据不同的数值添加到vector中。实现变更如下:
//7.3.3.1 Reference picture list modification syntaxvoid 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.modification_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_term_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.modification_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_term_pic_num = bs_read_ue(b); } sh->rplm.rplm.push_back(rplmtt); } while( rplmtt.modification_of_pic_nums_idc != 3 && ! bs_eof(b) ); } }}
2、与上类似,read_dec_ref_pic_marking函数变更如下:
//7.3.3.3 Decoded reference picture marking syntaxvoid read_dec_ref_pic_marking(h264_stream_t* h, bs_t* b){ slice_header_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_minus1 = bs_read_ue(b); } if(drpmtt.memory_management_control_operation == 2 ) { drpmtt.long_term_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_read_ue(b); } if( drpmtt.memory_management_control_operation == 4 ) { drpmtt.max_long_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、read_pred_weight_table函数中使用的num_ref_idx_l0_active_minus1为pps_t结构体的,这是错误的。正确的是使用slice_header_t结构体的num_ref_idx_l0_active_minus1。
for( i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++ )
要更改为
for( i = 0; i <= sh->num_ref_idx_l0_active_minus1; i++ )
其它一些细小的修改不在此文列出。源代码见github仓库:https://github.com/latelee/H264BSAnalyzer的Branch_dev分支。具体如下:
https://github.com/latelee/H264BSAnalyzer/blob/Branch_dev/H264BSAnalyzer/h264_stream.h
https://github.com/latelee/H264BSAnalyzer/blob/Branch_dev/H264BSAnalyzer/h264_stream.cpp
李迟 2015.9.28 晚
- 关于h264bitstream的bug修正及完善
- 解决h264bitstream的一个bug
- 关于Ehlib的ReadOnly小BUG修正。
- 关于TabControl控件的bug修正
- 关于xib连线错误的bug修正
- U3Terrain的一个BUG及修正
- 修正bug的方法
- CCEditBox的bug修正
- 关于cocos2dx播放音效的bug以及修正方法
- 分享:Microsoft IE Webcontrols Treeview的一个bug及修正
- C# 修正DataGrid bug引起的问题及反思
- CVE-2017-7269的几个技巧及BUG修正
- 修正XPMenu的两个Bug
- BugFree 的一个 bug 修正
- Subversion分支的Bug修正
- 关于getElementsByClassName的修正
- 关于《基于汉明距离的LSH图像检索算法》代码的一些bug修正
- Fancybox在ie6下关闭按扭及阴影效果不显示的bug的修正
- JavaScript 概述
- 关于指针概念易混淆点
- java中的“回车”与“换行”
- linux防火墙实现端口转发、端口映射及双向通路
- iOS解析json
- 关于h264bitstream的bug修正及完善
- 0. elipse使用方法及技巧
- HDU 5493 Queue
- UDP(面向无连接)的socket编程
- 黑马程序员--Java基础--05--IO流1
- 常识判断-国情社情与时政
- java 的排序算法
- 浅谈Java中的hashcode方法
- Java静态内部类