前文 《简单解析海康PS流获取H264》 针对海康摄像头的PS流解析做了简单处理,基本逻辑是正确的,但最近几个摄像头出现了一些奇怪的问题,需要针对相关现象进行查询。
RTP传输层
项目中为了可靠处理且因其他原因使用了TCP来传输28181的RTP数据,根据 rfc4571 记录,使用TCP传输的时候只需要在RTP包之前打上2个字节的长度,用来控制,毕竟TCP是流式传输,只能靠长度字段进行包的区分。
因此使用了TCP方式的RTP看起来问题不大,简单处理下就可以提取出PS数据了,事实也基本如此。但是出问题的摄像头却经常在解析RTP的时候出错,即判断RTP标志和SSRC出错,证明不是RTP包或者说包错乱。经过调试,打印出RTP头的所有信息,确实是在某个包后就出错了。打开二进制进行查看,发现出错之后往后部分数据之后,还能发现新的RTP包,看来是丢数据了。
将抓包数据写个测试程序测试,测试程序在解析RTP出错之后,往后查新的RTP包(主要靠SSRC),然后打印每个包的时间戳和序列号,发现确实是中间丢了几个包,TCP还能丢包?再看看日志发现,出现问题的摄像头都是上传速度非常慢的摄像头,即每秒仅能上传几帧视频的,而且丢包丢的都是I帧,毕竟I帧非常大。
因此猜测摄像头本身逻辑可能有点问题,即内部编码数据后,可能累积了大量未发送的数据,然后进行了内部丢包,而且这个丢包应该并没有按照一个RTP包去丢,而是直接丢弃的缓存数据,因而造成了上述问题。当然这只是根据现象的猜测,至于具体嘛,咱也不知道,咱也没有问。
还有一个现象是,这种丢包发生一会之后网络连接就被摄像头给断了。因为暂时不确定其他推流速度正常的摄像头是否会偶发这种现象,因此暂时任务可能偶发,针对性的类似测试程序一样,出现问题了通过查找下一个包来缓解挽救。但这由于丢包肯定会导致解析媒体数据出现错误,也就是下面的问题。
PS解析的错误处理
网络丢包造成的无法解析
如上,在丢包后,肯定会造成数据无法解析,这个时候肯定不能再继续处理了,肯定要结束当前的解析状态。也就是要上面网络层的配合,即网络层发现丢包之后要反馈给PS解析,让PS解析器及时的停止和重置,具体说来,大概是如果当前已经解析了一些媒体数据了,则提交这些数据,等待下一个PS包的到来(0x000001ba)。
PS数据格式错误?
在没有丢包的情况下,在解析PS的时候依然出现了问题,其格式大概如下
如上 0x000372F0 偏移处是前一个PES包(大小65478),里面解析了一个I帧0x000372FC,然后下一个PES包是 0x0004C72C 偏移处。二者偏移远远超过了 0xFFFF 大小,而PES的大小就是两个字节表示的。那么这就意味着格式有误,同时在RTP层解析确认此处的RTP流是顺序的,是没有丢包发生的。
虽然这个软件能解析出来后续的,但确实是对不上格式定义的,那这个也是一个坑。这个地方我也打算同上处理,解析的时候发生错误时候,查找下一个 0x000001XX 即可。同时也会兼顾RTP层的包及新的PS包 0x000001BA 出现。
其他问题
PS中媒体的真正时间戳
一般一个PS中存在了一个时间戳的视频包和一个时间戳的音频包,但是这个音频包和视频包可能时间戳是不相同的,为了表示准确,解析的时候尽量是按照时间戳变化后提交一次数据,无论是音频还是视频,基本上时间戳就没问题了。