WebRTC连接抖动引起的SRT推流不稳定解决方案

WebRTC和SRT都是热门的技术栈,为了验证其在音视频传输的低延时性,引入了流媒体服务器SRS,开箱即用的快速部署,让闪电不用分精力做别的,直击核心诉求。以下为公众号“吾视闪电”,作者:“吴江旻”的分享。

提出问题

原本计划摄像头用SRT推流到SRS,用RTMP观察延时数据,意外发现WebRTC也可以播放,而且秒开视频。于是在摄像头硬件上添加音视频码流推到SRS,在测试过程中发现浏览器播放端撑不过一晚即会中断,而且只有重启SRS或者摄像头才可以恢复。

分析问题

后来又发现SRS支持SRT拉流播放,于是用FFPLAYER播放SRT地址,即使浏览器播放端中断了,SRT拉流播放还是可以播放的,于是确认摄像头加上音视频的推流模块并不是引起SRS中断浏览器播放的原因。

但通过SRS的日志又发现一些出错信息,所以找了第三方推流软件进行再验证,使用专业版芯象导播软件经过一晚测试,浏览器播放端却没有中断。推流端和流媒体都没问题,难道是WebRTC的问题?

带着疑问,只能向谷歌请教了,好在之前看过一些Chrome调试WebRTC的文章,知道有个chrome://webrtc-internals网址可以调试网络状态和数据收发情况。也没发现任何问题,这样三端没问题即都有问题了。

经过反复测试SRT拉流,虽然会中断播放,但重新播放仍然能打开视频。于是剩下的排查手段只有分析SRS日志了,其实日志中出现serve error code的地方有三、四种,并不好确认是哪个出错码才引起问题现象。于是记录出现问题的时间,测试时摄像头是对着时间钟的,中断会停在某个时刻,这样就可以分析出引起问题的大概时间,最后从日志里发现出现serve error code=5011会引发问题。

再结合日志分析整个架构,摄像头通过SRT推流,先到SRS的SRT服务,然后转封装给RTMP服务,最后转RTC封装给浏览器播放端。这个过程里,SRT服务和RTMP服务是服务器本地localhost传输,理论上不会中断的。

在srt_to_rtmp.cpp中有个rtmp_client对象,负责把SRT数据转封装publish给RTMP服务。在on_ts_audio函数里需要判断是否有初始化过_aac_specific_config,该变量是string类型,保存了AAC的ADTS解码参数。每次建立RTMP推流即会发送codec.aac_packet_type=0(SrsAudioAacFrameTraitSequenceHeader)类型的消息包。在srs_kernel_codec.cpp中从收到的RTMP消息包中,判断acodec->is_aac_codec_ok是否收到SrsAudioAacFrameTraitSequenceHeader消息包。没收到即通知rtmp_client关停RTMP推流,因此导致5011错误。

WebRTC连接抖动引起的SRT推流不稳定解决方案
图1:音频SRT推流到RTMP服务流程图

同样在on_ts_video函数里需要判断是否有初始化过_h264_pps和_h264_sps,两变量都是string类型,分别保存了H.264的pps和sps解码参数,每次建立RTMP推流即会发送SrsVideoAvcFrameTraitSequenceHeader类型的消息包。在srs_kernel_codec.cpp中从收到的RTMP消息包中,判断vcodec->is_avc_codec_ok是否收到SrsVideoAvcFrameTraitSequenceHeader消息包,没收到即报音频同样错误。

WebRTC连接抖动引起的SRT推流不稳定解决方案
图2:视频SRT推流到RTMP服务流程图

解决问题

定位出引起问题的地方,以及分析了代码流程后,再回头从SRS日志中发现RTMP服务和浏览器播放端之间网络抖动时断开了连接,一段时间后没有视频消费者,会导致关闭RTMP服务的Publish线程,而SRT服务在收到设备推送的SRT数据,又会重新连接到RTMP服务。连接后需要重新发送音频和视频的解码参数(ADTS,SPS,PPS)到RTMP服务,但SRT服务没有关停过,而SRS此处逻辑忽略了此时需重发这些信息,以及清除发送缓冲(_send_map)。需清除_send_map是因为缓存中还有不带ADTS的音频消息包,一旦发送到RTMP服务就出现5011错误,在srs_app_conn.cpp的资源管理器(SrsResourceManager)中强制把RTMP当作僵尸线程关闭,如此这般循环使得浏览器即使重启也打开不了视频。

首先在rtmp_packet_queue对象中增加clear_queue函数,在rtmp_client每次connect中清除_send_map缓存,代码如下图3、图4。

WebRTC连接抖动引起的SRT推流不稳定解决方案
图3:新增清除发送缓存函数
WebRTC连接抖动引起的SRT推流不稳定解决方案
图4:在connect中调用清除发送缓存

为了每次新建RTMP推流能初始化音视频解码参数,在rtmp_client的close函数中需重置_aac_specific_config、_h264_spa和_h264_pps,代码见图5。

WebRTC连接抖动引起的SRT推流不稳定解决方案

结论

问题能解决,说明SRS前辈搭的框架优秀毋庸置疑。但对于嵌入式设备接入,还可考虑硬件资源受限,让设备开发者在低内存资源的情况下实现高性能网络传输,例如在SRT封装MPEGTS时能否不用累积完整一帧音频或者视频数据发送,大家一起探讨探讨!

作者:吴江旻
来源:吾视闪电
原文:https://mp.weixin.qq.com/s/MbYMRTXJyjug_TCT7Z23Kw

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

发表回复

登录后才能评论