要想深入学习视频,就必须对h264文件有所了解,我就以前面海思摄像头生成的h264文件为例说明一下h264的基本知识,以方便后期rtsp传输视频时对h264打包。
附件:Hi3518编码H264
请先下载附件里的文件,里面有源代码、生成的h264文件、调试输出的打印信息。我们首先打开“h264数据分析”文件夹里的“log20171229103150_printf.txt”文件,这个文件是调试输出的打印信息。从打印信息可以看出摄像头是AR0130,720P,30fps,这种图片格式需要的内存大小为u32BlkSize=1491840。下面的一系列数据就是hi3518生成h264数据时的打印信息。
附件内容:
1、“mpp”文件夹里是源代码
2、“h264.si4project”是source insight4工程文件,用source insight便于阅读代码。
//如果你用source insight3阅读代码,因为编码问题,里面的中文注释可能会是乱码,推荐用source insight4。
3、“h264数据分析”文件夹里的log20171229103150.h264是原始的h264数据文件,是二进制文件,必须用二进制工具才能打开;
4、log20171229103150_data.txt是由log20171229103150.h264文件转码为txt,以便用记事本、notepad这样的文本工具打开,以便于观看数据;
5、log20171229103150_printf.txt是hi3518运行过程中输出的打印信息。
可以用eseye_u.exe解析h264数据log20171229103150.h264,显示图片。
用ultraedit打来log20171229103150.h264文件查看里面的原始数据。
我们用notepad打开log20171229103150_printf.txt文件,看到h264调试信息如下:
//第一帧由4包
stStream.u32PackCount=4,stStream.pstPack[0].pu8Addr=0xb68c4040,stStream.pstPack[0].u32Offset=0,stStream.pstPack[0].u32Len=18
stStream.u32PackCount=4,stStream.pstPack[1].pu8Addr=0xb68c40c0,stStream.pstPack[1].u32Offset=0,stStream.pstPack[1].u32Len=8
stStream.u32PackCount=4,stStream.pstPack[2].pu8Addr=0xb68c4140,stStream.pstPack[2].u32Offset=0,stStream.pstPack[2].u32Len=9
stStream.u32PackCount=4,stStream.pstPack[3].pu8Addr=0xb68c41c0,stStream.pstPack[3].u32Offset=0,stStream.pstPack[3].u32Len=3620
//另一帧
stStream.u32PackCount=1,stStream.pstPack[0].pu8Addr=0xb68c5040,stStream.pstPack[0].u32Offset=0,stStream.pstPack[0].u32Len=12
u32PackCount: 一帧包含几个h264 nalu
pstPack[?].pu8Addr: 第?包的虚拟首地址
pstPack[?].u32Len: 第?包的大小
第一行stStream.u32PackCount=4,stStream.pstPack[0].pu8Addr=0xb68c4040,stStream.pstPack[0].u32Offset=0,stStream.pstPack[0].u32Len=18
表示这一帧视频有4个h264 nalu,第一个包的虚拟首地址为stStream.pstPack[0].pu8Addr=0xb68c4040,有效数据紧跟在首地址后面,所以偏移stStream.pstPack[0].u32Offset=0,第一个大小为stStream.pstPack[0].u32Len=18,
所以在log20171229103150.h264数据文件里看,第一个包的起始码00 00 00 01在0x00000000处,那么第二个包的起始码应该在0x00000000+18=0x00000012处,看数据文件,果然第二个起始码00 00 00 01在0x00000012处。后面的三行都是第一帧的数据,分析方法同上。
第一帧的第4个包大小为stStream.pstPack[3].u32Len=3620,其开始位置为0x00000023+3620=0x00000e47,看数据文件,果然下一个00 00 00 01在0x00000e47处。当然在0x00000e47处的包是属于第二个帧了。前面说过要想解析一个h264图片必须需要0x67sps,0x68pps,0x65关键帧。看第一帧数据果然少不了0x67sps,0x68pps,0x65关键帧这三个nalu。至于中间夹杂了一个0x06nalu是补充增加信息nalu。现在我们可以用eseye_u.exe解析出图片,如果我们删除0x67,0x68,0x65中的随便一个nalu就会发现eseye_u.exe解析不了图片了,也验证了我们前面说的h264必须包含0x67,0x68,0x65这3个nalu。
用eseye_u.exe解析整个log20171229103150.h264发现总共有13个红块,这13个红块就是关键帧,里面包含0x67sps,0x68pps,0x65关键片,其余的是蓝块,非关键帧,依赖于前面的关键帧。