上个月着手写的那个H264码流分析工具基本完成基本的功能,为了显摆,还在部门公布了,不过使用效果不及几十刀的正牌分析工具那样功能强大,速度快。但是,自己从这里面学到了一些东西,还是不错的。当然,肯定是向着更高更强的层次看齐。——所以那个工具还在完善中。
上周同事拿了一下他自己录的视频给我,我用那个工具打开,发现界面显示的宽、高显示不对,SPS中的分析的字段不正确(对,就是工具分析后的参数不正确)。对比正牌工具的分析结果,毫无悬念地怀疑是自己工具的问题,于是叫同事截图给我(正牌工具只能在一台电脑上安装,在他电脑上),当天晚上回去调试代码,终于解决了这个问题,原来是h264bitstream本身的bug。本来想向h264bitstream项目提意见的,但人家好几年没更新了,于是就不了了之了。
说回bug本身,经过调试,发现只要是sps_t的seq_scaling_matrix_present_flag字段为1,分析的结果就不正确。于是定位到下面的代码:
if( sps->seq_scaling_matrix_present_flag )
{
for( i = 0; i < 8; i++ )
{
sps->seq_scaling_list_present_flag[ i ] = bs_read_u1(b);
if( sps->seq_scaling_list_present_flag[ i ] )
{
if( i < 6 )
{
read_scaling_list( b, sps->ScalingList4x4[ i ], 16,
sps->UseDefaultScalingMatrix4x4Flag[ i ]);
}
else
{
read_scaling_list( b, sps->ScalingList8x8[ i - 6 ], 64,
sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] );
}
}
}
}
对比分析正确截图的对应的字段,seq_scaling_list_present_flag数组的值不符合,继续定位到bs_read_u1和read_scaling_list函数以及代码里面的判断条件。bs_read_u1其实没有什么好怀疑的,单步看结果是正确的,继续看read_scaling_list,发现该函数有一个判断:
void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int useDefaultScalingMatrixFlag )
{
int j;
if(scalingList == NULL)
{
return;
}
}
这里会不会有问题呢?比如,传递了NULL,直接返回,不再执行下去。因为就是从这里开始错误的,有理由作出合理的怀疑,于是打印出传递给scalingList的参数,发现是0,竟然是NULL!!!也就是说,sps->ScalingList4x4[]数组的元素是0,再看前面的代码,赫然有下面的语句:
memset(sps, 0, sizeof(sps_t));
——后面又没有对这个数组进行操作,不是0才怪!
再看对应的成员参数的声明:
int* ScalingList4x4[6];
int* ScalingList8x8[2];
声明了指针,感觉上没有问题,但是在调用上却误将ScalingList4x4和ScalingList8x8的元素的值(即0)传递进去了。知道了原因,修改就容易了。将两者的声明去掉“*”,不要用指针。下面是修改后的代码
if( sps->seq_scaling_matrix_present_flag )
{
for( i = 0; i < ((sps->chroma_format_idc!=3) ? 8 : 12); i++ )
{
sps->seq_scaling_list_present_flag[ i ] = bs_read_u1(b);
if( sps->seq_scaling_list_present_flag[ i ] )
{
if( i < 6 )
{
read_scaling_list( b, &sps->ScalingList4x4[ i ], 16,
sps->UseDefaultScalingMatrix4x4Flag[ i ]);
}
else
{
read_scaling_list( b, &sps->ScalingList8x8[ i - 6 ], 64,
sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] );
}
}
}
}
综上所述,最终的修改就是去掉两个“*”,加上两个“&”。
修改很简单,但知道修改的原因却要经过一番努力——而这,就是不为人知的背后的辛酸。
PS:最近领导找我谈了加薪问题,无意间听到一些事,想了两宿,觉得以后还是少显摆自己的水平比较好,有时间有心情搞点东西,还是直接在网络上发表文章的好。
李迟记于2014年3月22日