上篇文章中对GB28181的协议做了简单描述,这个还是很简单的,通过协议我们最主要的实现:
- 摄像头的注册
- 点播和关闭指令
摄像头在点播后,会向指定的UDP端口推送视频流,这里耗费了不少时间
收流
首先我们需要启动一个UDP服务,将摄像头发送的数据接收,JAVA启动UDP端口的例子很多,就不举例了。一般每一帧大概1500个字节以下,收到数据后放到一个byte[]中,后面就要解析读取H264裸数据了
拆包
GB28181这块对内容的描述比较简单,造成走了很多弯路。
最早我直接去掉RTP12个字节的包头,然后写入一个文件中去验证,结果这个文件居然也可以播放,一些地方有一点花屏。
实际上包结构也比较简单,整体就是
12字节RTP包头 + PS数据
所以第一步 先把12个字节包头去掉
这里先贴个图
PS数据的格式处理起来比较麻烦
格式如下
关键帧
PSheader| PS system header | PS system Map | PES header | h264 raw data
非关键帧
PS header | PES header | h264raw data
关键帧也叫I帧,非关键帧是P帧
借用https://blog.csdn.net/comhaqs/article/details/102702713中的3张图
这篇博客写的很好 我们获取其中绿色的部分。而我在实际抓包的时候,发现这个有一部分内容,就是我红框的地方,上图没有描述。
后来查阅到,这部分叫做SEI,这部分实际测试 不处理也不影响结果。
我在收流的时候,启动一个线程来接收流,拆包处理后,把数据传送给另外一个线程进行转码。
转码
…
还是用C++把 JAVA可以做到,图象也能出来 但是不稳定,JAVA做SIP部分就行了