GB28181开发(五) --GB28181设备接入

开源项目地址(未完成)

https://github.com/comahqs/mdfactory

项目主要需求如下:

1、GB28181设备接入

2、实现视频流转文件或视频流(例如RTSP)

3、实现视频流转GB28181

项目使用pjsip库实现GB28181设备接入,网上也有很多例子,但都不是很完整,导致我绕了好多弯路。pjsip启动监听的流程都类似,网上也有很多,大家可以看源码。注册注销流程、心跳流程也都好理解,主要问题是在发起INVITE请求方面,在函数server_sip::start_play中就模拟了SIP服务器主动发起实时视频请求流程。目前代码只处理了h264,所以记得将摄像头的格式调整为h264,另外我这边测试直连的时候都有udp丢包现象,所以最好先降低视频流码率。

打包sdp信息发送给摄像头后,交互流程pjsip已经处理好了,你只要在pjsip_inv_usage_init注册的对应回调里处理剩余逻辑就可以了。网上一般建议在on_media_update回调里开启rtp接收并发送回应包。这里将GB28181协议的sip服务器和媒体服务器整合到一起,减少交互流程。

通过pjmedia_transport_udp_create创建rtp监听,pjmedia_transport_attach绑定数据回调,pjmedia_transport_media_start启动监听流程,最后那个启动一定要有,我就在这停了好久,网上有些代码没有这个启动。

在rtp回调里通过pjmedia_rtp_decode_rtp剥离rtp协议,剩下的就是你需要的数据了,一般摄像头只支持ps格式,需要手动剥离ps协议。

PS解码

PS格式数据包分两种,一种是由SPS、PPS和帧数据的包,SPS记录了视频流的相关信息,可以认为这种包是关键包;另一种是只有帧数据的包。一个数据帧很大,但RTP包长度有限,所以一般一个数据帧会分割成多个包,按顺序发给对方。

关键包开头结构如下

普通包开头结构如下:

两种帧的后续包结构如下:

我们要做的就是去掉PS格式相关信息,把绿色部分剥离出来。按照PS协议,所有头部都是00 00 01开头,然后加个头代码,然后相关数据。我们需要先判断是那种头部,然后根据长度跳过这些头部,我们只关心PES头部,代表视频数据,以及未画出的音频(0x000001C0),注意数据帧的长度都是高位在前,低位在后,下面描述都是从第0个字节开始表示位置.已知的头部及处理如下:

0x000001BA PSH头,PS包开头,表明一个PS包的开始,至少14个字节,最后一个字节(第13字节)的后3位代表了额外在14字节上扩展了多少个字节。直接计算PSH头长度后跳过。头长度=14+扩展头长度

0x000001BB SYS头,标题数据,第4到第6字节表示剩余头长度,即头长度=6+剩余头长度,直接跳过

0x000001BC PSM头,与SYS头计算一样,其中包含了视频和音频格式信息,目前直接跳过

0x000001E0 视频数据,至少9字节,第4至第5字节描述整个包的字节,第8字节描述包头扩展长度,包头后面是数据,所以数据起始位置在包头开始+9+包头扩展长度,数据长度是整个包长度-9-包头扩展长度

0x0000010C 音频数据,同0x000001E0

0x000001BD 私有数据,同0x000001E0 ,直接跳过

具体的PS格式可以参考网上的其他资料,另外,如果数据中包含0x000001,按h264协议会进行转义,即变成0x00000301,涉及到3个转义 0x000001 -> 0x00000301   0x000002 -> 0x00000302  0x000003 -> 0x00000303

提取绿色部分可以直接二进制写到文件里,就是h264文件了。h264和h265格式定义不一样,有些摄像头默认是h265格式,记得修改成h264

参考网页:https://blog.csdn.net/ichenwin/article/details/100086930

你可能感兴趣的:(gb28181)