在用海康SDK获取H264视频流的时候,其实从海康的SDK里面基本是没有的,海康的SDK介绍使用是通过自身的PlayM4解码成图片的,并非我们想要的H264。项目里面使用的是海康提供的AnalyzeData库,但是我并没有从海康官网找到下载,应该是PS格式解析库。
分析
其实通过Wireshark本地抓包,抓摄像头IP的包,在程序请求后会发现确实是TCP连接上的PS格式的流,在设置了视频格式为H264的情况下我们就可以进行解包了。
网上确实有很多解包的代码,但是我使用过,某些情况下就产生了core了,很明显了内存使用有问题,打算自己实现。在查看了PS的规范,我觉得不太可能实现了,基于我们的目的通过最简单的方式取出H264即可,其他信息暂时忽略。
格式
好在PS包格式也不是特别难,PS包开始以 0x00 0x00 0x01 0xba
,然后内部包含了很多PES包,开始标志之后,紧接着看第14字节(包含00 00 01 ba)的值,该值与0x07与之后就是扩展长度,也就是说包长为扩展长度加14。跳过上述长度后,就开始了PES包。
PES包也是以0x00 0x00 0x01 XX
开始,其中XX是各个包不同,视频包为0xe0,音频包为0xc0。 类似的确认包格式后,接着就是2个字节的长度(注意都是大端字节序,下同),这个长度表示后续数据长度,跳过起始的6个字节后,我们处理视频包的数据时,第三个字节表示扩展头大小,因此跳过3加扩展头大小,剩下的就是H264裸流数据了,注意自己计算各个长度的大小。
通过上面简单的算法,很容易就拿到了H264数据 了,音频也是类似的,不过我暂时不关心。
代码
C++实现的PS提取H264的类实现如下
class PsPacketParser { |
上面的代码入口参数为单个PS包,如果拿到的不是单个包,通过0x00 0x00 0x01 0xba
分割即可,这块处理也不难,或者根据上述代码改造成缓存版即可。其他语言也可以根据上面的算法思路简单处理,已通过C#实现,确实相对简单,至少比第三方库使用方便多了。