问题现象:使用全志的编码库,编写了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)的表:
一个是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。为了灵活处理,决定这段自己用软件实现吧。