Janus网关的集成与优化( 三 )


核心层主要负责SDP的协商以及ICE连接的建立,UDP媒体数据的接收和转发也在核心层里完成 。而插件和JS SDK的通信使用的是TCP协议, 它是通过传输层来完成的.
传输层主要负责在JS SDK和网关之间传输控制数据, 插件自定义消息等 。传输层支持多种常见的传输协议,比如HTTP、WebSoket等 。
3 Janus与自研RTC的集成

Janus网关的集成与优化

文章插图
 
第三部分是Janus与自研RTC的集成,主要包含三个小节,分别是系统架构、音视频互通、集成效果 。
3.1 系统架构
Janus网关的集成与优化

文章插图
 
这张图片是高度简化后的结果,像自研RTC集群里的媒体调度、负载均衡、线性扩展等内容都没有在这里表达出来,主要是希望能突出与集成相关的内容 。图中大致包含三个部分:自研RTC系统、Janus网关以及中间绿色箭头代表的媒体通道 。
我们按上图从左至右, 来看一下通信流程 。
首先是用户A通过任意一个平台的客户端连接到自研RTC集群,通过中间的媒体通道,间接地和连接到网关上的浏览器用户B进行音视频互动 。在Janus网关和浏览器用户B之间主要传输RTP格式的音视频数据和自定义格式的笔迹数据 。其中的音视频数据走的是P2P的传输通道,笔迹数据走的是WebSocket通道 。整个集成核心的部分是位于Janus网关和自研RTC集群中间的绿色箭头所代表的音视频转换,更具体的来说,就是自定义封装格式和RTP封装格式的转换 。
前面介绍P2P媒体传输通道时提到RTP最终是通过UDP的传输协议发送出去的 。
为了避免IP分片, 发送的UDP包不能太大,具体一点是不能超过路径上MTU的限制,一般来说,以太网上的MTU的最大限制是1500个字节 。实际过程中需要除去IP协议头和UDP协议头开销,剩下大概也就1400多个字节, 因此RTP包不能超过这个限制, 这个限制会影响到RTP的封包过程 。
3.2 音视频互通
在我们的系统中音频采用Opus编码,视频采用H.264编码,WebRTC(主要是Chrome浏览器)也支持这两种编码,因此不需要在网关上进行转码了 。
Janus网关的集成与优化

文章插图
 
图中展示的是音频数据的转换, 包含了音频数据从采集到封装成RTP的过程 。从上往下, 首先是声卡采集到PCM数据,一般是按10毫秒或者20毫秒这种固定长度进行组织. 经过Opus编码器, 根据PCM数据的内容特征, 编码成长度不一样的编码数据. 编码后的音视频数据一般是几十到几百个字节左右 。这样的数据量可以直接在单个RTP包中进行携带,因此声音的RTP封装非常简单,只需要在数据的前面追加上RTP头部就行 。
RTP头部中主要的两个字段是sequence number和timestamp, 即序列号和时间戳 。因为UDP传输是一个不可靠的协议,在传输的过程中可能会发生丢包或者乱序到达 。序列号可以帮助接收端正确地组织接收到的数据,根据序号的缺失情况可以知道哪些数据包丢失,根据丢失包的序号可以要求发送端进行重传,从而保证传输质量 。时间戳主要是辅助播放端进行声音的同步播放 。
整个过程倒过来看,就是如何从浏览器发过来的RTP数据中提取编码数据的过程 。在提取出编码数据以后就可以封装成自研RTC格式,通过自研RTC集群再转发到客户端上,并在客户端上进行播放 。
接下来是视频的转换 。
H.264视频转换在RFC6184文档里有详细的规定和说明 。相对于音频来说,视频转换要复杂一些,这是因为图像数据编码后,它的数据帧往往比较大,会超过RTP包的大小限制 。
Janus网关的集成与优化

文章插图
 
该图是视频数据转换成RTP包的示意图 。还是从上往下看,首先摄像头采集原始的视频图像,一般是YUV格式的,经过H.264编码后生成H.264的数据帧 。数据帧本身是有内部结构的,它包含一个起始码,后面跟着NAL单元,由多个这样的结构组成编码后的数据帧,在转换的过程中,第一步是要把起始码去掉,再提取出单个的NAL单元数据 。然后根据NAL单元数据能否封装到单个RTP包中,分别封装成三种不同的封装格式 。
图中左边是单个NAL单元的封装,在NAL单元比较小的情况下使用. 中间是单元片段的封装,在单个NAL单元大小超过RTP包限制的情况下,采用该封装格式 。
右边是多个NAL单元聚集到一个RTP包的封装过程,这里主要针对NAL单元很小,RTP包可以同时携带多个NAL单元的情况,封装到一个包里,可以减少发包的数量 。同样,封包过程需要正确的填充RTP头部的时间戳和序列号 。


推荐阅读