WebRTC进阶流媒体服务器开发(四)Mediasoup源码分析之底层库
一:Mediasoup库的JS部分(与C++交互)
整个Mediasoup库通过Nodejs管理,比如整体逻辑、worker、router、producer、consumer...都是通过JS进行管理的。
其底层的数据传输是通过C++部分进行控制的,通过NodeJs来控制C++部分,以实现整体的数据传输效果。
(一)Mediasoup JS目录---调用底层C++进行通讯
AudioLevelObserver.js 检测声音大小,通过C++部分测量出声音之后,返回给该js文件中的对象,再返回给应用层展示音量
Channel.js 与C++部分进行信令通讯
Consumer.js 消费者
DataConsumer.js
DataProducer.js
DirectTransport.js
EnhancedEventEmitter.js EventEmitter的封装,事件的处理
errors.js 错误信息
index.js mediasoup库的索引
Logger.js 日志管理
ortc.js 与SDP对应,以对象的方式描述SDP信息
PayloadChannel.js
PipeTransport.js Worker之间router之间数据流的转发
PlainTransport.js 普通的RTP数据传输通道
Producer.js 生产者
Router.js room相关操作
RtpObserver.js RTP观察者
RtpParameters.js
scalabilityModes.js
SctpParameters.js
SrtpParameters.js
supportedRtpCapabilities.js 能力支持相关,媒体协商相关
Transport.js 所有transport的基类
types.js
utils.js 常见的工具函数
WebRtcTransport.js 浏览器使用的传输
Worker.js 进程
(二)Mediasoup JS类关系图
1.几乎所有类都继承自EnhancedEventEmitter,每个对象都可以发送事件
2.每个worker代表一个节点,内部有多个Router,组成Routers结构。每个Worker中都有一个channel,与C++进行通讯
3.对于每一个Router房间来说,是包含Tranports和Produces
4.Transport包含Produces与Consumes,其包括多个子类,如WebRtcTransport(浏览器数据传输)、PlainRtpTransport(非音视频)、PipeTransport(不同router之间数据流转)
(三)Mediasoup JS作用
(四)实例createRouter:应用层-->JS层-->C++层
1.await this._channel.request('worker.createRouter', internal);
传入字符串和参数,在request中构建json数据,传给C++层
2.new Router在JS层产生逻辑关系,进行管理
二:Mediasoup C++库类关系(核心)
包括基本管理,比如:流传输,数据加解密,数据安全验证,流数据流转,带宽评估...
(一)Mediasoup核心类关系图(与JS类图相似)
1.最核心是Router类,房间概念,包含Consumer、Producer,Transport子模块,关系对应1:n
2.Consumer中含有多种子类,如:SimpleConsumer(音视频流)、PipeConsumer(Router之间数据流转)、SvcConsumer(分层、增量)、SimulcastConsumer(分层)
3.Producer,接收共享者传输的流
4.Transport分为3种,同前面JS介绍一致,TransportTuple元组存放本地socket、远端socket、IP、端口
(二)Mediasoup核心类关系详细图
1.对于4种消费者,都包含RtpStreamSend对象,消费者发送数据给客户端,通过RtpStreamSend方法。RtpStreamSend继承自RtpStream,这个类处理Rtp数据流的收发。RtpStream使用到了RtpPacket,这个包是用于对Rtp数据包的分析,Rtp数据有数据包头,对于包头每一个字段的定义都是在这个Packet里面操作的
2.因为要对整个数据进行处理,所以使用SeqManager,序列管理器。服务端推送给客户端的数据流是会重新排序的,排序的时候便会依靠这个SeqManager,它会记录某个SSRC所对应的Sequence,以此为起始位置,然后后面的每个包都向下递增一个数
3.Producer作为服务端的生产者,它是用来接收共享者发送的数据流,所以它里面包含多个RtpStreamRecv,是一对多的关系(为什么是多个RtpStreamRecv呢?因为数据的接收有可能会丢包,丢包重传的也算作一路流,对应的音频的丢包也是需要重传)
4.作为数据的接收端,RtpStreamRecv使用到了NackGenerator丢包产生器。接收端能够知道有没有丢包,因为数据包有Sequence,比如发送了100个数据,前50个数据是连续的,但假设当50之后是55,Recv端就知道丢了 51、52、53、54 这4个包了。丢包之后如何解决呢,有两种方式:
-
Fec:在每个包增加一些冗余,它能计算 出丢失的音频包或视频包
-
Nack:它会告诉发送端丢了哪些包,发送端会根据策略,若时间比较短的话,会把丢失的包补上来,具体补哪些包就是根据NackGenerator产生的
5.Transport分为3种,WebRtcTransport(浏览器数据传输)、PlainRtpTransport(非音视频)、PipeTransport(不同router之间数据流转)。TransportTuple元组存放本地socket、远端socket、IP、端口
6.最核心的是WebRtcTransport,与浏览器进行数据传输。首先其包含UdpScoket与TcpServer对应两个链接,可以与客户端连接通信
7.对于UdpSocket与TcpServere,其继承自PortManager端口管理器,对于Mediasoup来说,默认是从40000到49999共一万个端口号。UdpSocket和TcpServer通过PortManager进行对端口号的管理,首先确定端口号有没有被占用,没有被占用就使用该端口号对数据传输;若被占用,就根据PortManager的策略往后跳。注意Udp和Tcp的使用是互斥的
8.DtlsTransport:使用dtls对Rtp包进行数据加密的协议,同时在这里面还使用到了Srtp协议,Srtp协议分为数据的收与发,所以在WebRTCTransport中有Srtp send和recv这两个Session
9.RembClient/RembServer:这两个主要用于对带宽的评估,既可用于client端也可用于server端。对于共享者来说,Mediasoup的WebRTCTransport就是RembClient端;对于消费者来说,就是RembServer端
10.IceCandidate:候选者包括Host、Server reflexive、Relay reflexive三种,对于WebRTC一般设置成Host,最高优先级
11.IceServer包括证书验证、指纹识别等一系列安全验证机制,它里面也包含了多个TransportTuple
12.TransportTuple:如果使用TCP连接,它里面便含有TcpConnection