h.264编码异常问题

问题现象:使用全志的编码库,编写了Camera录像程序,但是录像的视屏播放总是存在异常,感觉是录像了十几秒,一秒不到就都给播放完毕了。通过调节解码器参数,将frame_rate固定为25fps,播放就正常了。因此,目前猜测问题的原因是,录像文件的header有误。也就是sps,pps存在问题。

问题排查:

首先,h.264编码的文件头是sps(序列参数集),pps(图像参数集),先看一下异常视频文件中的sps,pps是什么样的。

通过ghex解析录制的h264视屏。得到:

SPS: 00 00 00 01 67 4D 00 1F 96 54 02 80 2D 88

PPS: 00 00 00 01 68 EE 3C 80

I帧  : 00 00 00 01 65 .....

感觉录像程序也有点问题,录制的都是I帧,没有看到BP。。

继续,进一步细化解析,

ue(v):无符号整数指数哥伦布码编码的语法元素,左位在先。

se(v):有符号整数指数哥伦布码编码的语法元素,左位在先。

u(n):n位无符号整数。在语法表中,如果n是‘v’,其比特数由其它语法元素值确定

语法嘛,参照下面两个表就行了。

一个是ue(v)的表:

ue(v)解ç è¿ç¨

一个是se(v)的表:

se(v)也称有符号指数哥伦布编码,所以当描述子为se(v)时,它的输出有可能为负。而且当描述子为se(v)时,它的输入为上述过程解析出来的codeNum。意思是什么呢?如果遇到se(v),需要先调用ue(v),得出codeNum的值。然后调用se(v)的解析过程,se(v)的输出即为语法元素的值。 

上面的两张图,来自下面的链接。
作者:金架构 
原文:https://blog.csdn.net/u011399342/article/details/80472399 

最后,是参数说明表,这个网上搜一搜就有了

准备工作完成,那么开始了。

4D 00 1F 96 54 02 80 2D 88先转换成2进制。

4D              00             1F              96             54               

0100 1101 0000 0000 0001 1111 1001 0110 0101 0100

profile idc(u8) = 77(0x4d) main profile

constraint_set0_flag ~ constraint_set5_flag总共8位,都是0

level_idc(u8) = 31(0x1f)   

标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。当前码流中,level_idc = 0x1f = 31,因此码流的级别为3.1。

对于ue(v)的计算,最简单的是参考下图。

    0x96 54    1001 0110 0101 0100 b

   1...      ....    = seq_parameter_set_id: 0

    .001  01 ..  = log2_max_frame_num_minus: 4    由于profile idc为77,不在if条件中,所以直接变成这个。

   ....       .. 1. = pic_order_cnt_type: 0

 .... ...0 0101 .... = log2_max_pic_order_cnt_lsb_minus: 4

    ....  010.  =  max_num_ref_frames: 1    //猜测,这个就是都是I帧的原因。

    .... ...0 = gaps_in_frame_num_value_allowed_flag:0

换下一组数据,0x 02 80 2D: 0000 0010 1000 0000 0010 1101 b

0000 0010 1000 0:pic_width_in_mbs_minus1:79    //图片宽度= (79+1)*16 = 1280

000 0010 1101:pic_height_in_map_units_minus1: 44   //图片高度=(44+1)*16 = 720

0x88: 1000 1000  b

1... .... = frame_mbs_only_flag: 1

.0.. .... = direct_8x8_inference_flag: 0

..0. .... = frame_cropping_flag: 0

...0 .... = vui_parameters_present_flag: 0

额,解析完了,最后一个0x88中后四位,0x08啥意思啊???

解析的这段过程,最好对比engineer_james的解析,解析数据的含义,文章中也有介绍。

作者:engineer_james 
原文:https://blog.csdn.net/engineer_james/article/details/81750864 

PPS不想继续解析了,累。。。

现在的问题很明显了,如果h.264中,没有vui parameters信息,编码器应该怎么播放这个视屏??听说海康也是这样,算了,我这边的解决方案,就是找一个参照,然后自己加上vui_parameters信息。

如果想要带上帧率的,需要的参数是,framerate =time_scale/2*num_units_in_tick.以及fixed_frame_rate_flag = 1

the sps_pps :00
the sps_pps :00
the sps_pps :00
the sps_pps :01
the sps_pps :67
the sps_pps :4d
the sps_pps :00
the sps_pps :1f
the sps_pps :96
the sps_pps :56
the sps_pps :02
the sps_pps :80
the sps_pps :2d
the sps_pps :90
the sps_pps :80
the sps_pps :00
the sps_pps :00
the sps_pps :00
the sps_pps :80
the sps_pps :00
the sps_pps :00
the sps_pps :19
the sps_pps :40
the sps_pps :00
the sps_pps :00
the sps_pps :00
the sps_pps :01
the sps_pps :68
the sps_pps :ea
the sps_pps :43
the sps_pps :c8

新的sps_pps,麻蛋,还是有问题。这次是linux系统下,用video能够播放,但是在windows以及手机环境中,都没法播放。。。

还是得继续来了。

好吧,原因找到了,我这个是h.264裸流,需要封装成mp4格式,电脑才能播放。。。

全志提供了封装,但这个封装也不是开源的,同样是库+头文件的形式。CdxMuxer.h。看了一下,如果这样使用的话,需要插sd卡,并且保存路径没法改变。/mnt/sdcard/mmcblk1p1/*.mp4。为了灵活处理,决定这段自己用软件实现吧。