解决h264bitstream的一个bug

上个月着手写的那个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日
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值