mediasoup基础介绍
一、简介
webrtc:谷歌开源,跨平台,用于浏览器之间的实时传输音视频引擎(一对一)
mediasoup:流媒体服务器,实现多人在线实时互动。
二、mediasoup架构图(from web)
三、vrvmeeting中c++代码
启动mediasoup
worker.js构造函数中调用spawn,启动mediasoup-worker
// Create the mediasoup-worker child process.
this._child = spawn(workerPath, spawnArgs, spawnOptions);
运行worker
一、初始化,配置相关项
二、创建channel,用于接收及发生数据
int channelFd = std::stoi(std::getenv("MEDIASOUP_CHANNEL_FD"));
// Initialize libuv stuff (we need it for the Channel).
DepLibUV::ClassInit();
// Set the Channel socket (this will be handled and deleted by the Worker).
auto* channel = new Channel::UnixStreamSocket(channelFd);
三、运行worker
// Run the Worker.
Worker worker(channel);
mediasoup channel的创建
js:worker.js
// Channel instance.
this._channel = new Channel(this._child.stdio[CHANNEL_FD]);
c++:main.cpp(channelFd为3)
// Set the Channel socket (this will be handled and deleted by the Worker).
auto* channel = new Channel::UnixStreamSocket(channelFd);
var code = "f40d1b26-d2ee-4104-9ecc-42f58dfcb640"
注:实际实现的地方为handles/UnixStreamSocket.cpp中:
UnixStreamSocket.cpp详情
uv_pipe_init -> uv_pipe_open -> uv_read_start
// Start reading.
err = uv_read_start(
reinterpret_cast<uv_stream_t*>(this->uvHandle),
static_cast<uv_alloc_cb>(onAlloc),
static_cast<uv_read_cb>(onRead));
实际真正读取的接口:channel/UnixStreamSocket.cpp
int nsRet = netstring_read(reinterpret_cast<char*>(this->buffer + this->msgStart), readLen, &jsonStart, &jsonLen);
转成json,将相关数据解析并放到request类中(id,method,internal,data)
request = new Channel::Request(this, json);
将request传给worker
// Notify the listener.
this->listener->OnChannelRequest(this, request);
调用worker.cpp中的OnChannelRequest,根据requset的MethodId做不同的执行动作
1.WORKER_DUMP:拿到workerid和routers的数据值并返回
2.WORKER_UPDATE_SETTINGS:更新相关配置
3:WORKER_CPUWOEKSPEED:拿到CpuSpeed并返回
4:WORKER_NETWOEKSPEED:拿到NetName,上传速度,下载速度,并返回
5:WORKER_CREATE_ROUTER:创建router
6:ROUTER_CLOSE;关闭房间
7:ROUTER_CREATE_SYNCHRONIZATION_TRANSPORT
8:WORKER_REMOTE_BITRATE
9:其他MethodId:从request中拿到router,然后在router中执行HandleRequest
1:router = GetRouterFromRequest(request);
2:router->HandleRequest(request);
注意:信令返回方式:
request->Accept();//无返回数据时
request->Accept(json);//有返回数据时
accept()实现:libuv库的uv_write接口
router房间类
Request::MethodId为ROUTER_CREATE_WEBRTC_TRANSPORT:创建webrtc transport
从request中获取transportId,peerName,udpsocket,将其他数据存入RTC::WebRtcTransport::Options中,然后创建WebRtcTransport
if(Settings::configuration.isSinglePort){
webrtcTransport = new RTC::WebRtcTransport(this, this->notifier, transportId, options,udpSocket,peerName);
}else{
webrtcTransport = new RTC::WebRtcTransport(this, this->notifier, transportId, options);
webrtcTransport->m_peername = peerName;
}
Request::MethodId为ROUTER_CREATE_PRODUCER:创建producer
获取producerId,获取peerName,transport,Media::Kind,RTC::RtpParameters,RtpMapping rtpMapping,然后创建producer
auto* producer = new RTC::Producer(this->notifier, producerId, kind, transport, rtpParameters, rtpMapping, paused);
//Tell the Transport to handle the new Producer
transport->HandleProducer(producer);
this->mapProducerConsumers[producer];
//添加producer和peer关系
this->mapProducerPeers[producerId] = peerName;
Request::MethodId为ROUTER_CREATE_CONSUMER:创建consumer
获取consumerId,peerName,producer,创建一个cunsumer:
auto* consumer = new RTC::Consumer(this->notifier, consumerId, kind, producer->producerId);
//将consumer和producer进行关联
this->mapConsumerProducer[consumer] = producer;
//consumer 和peer关联
this->mapConsumerPeers[consumerId] = peerName;
WebRtcTransport类
auto* udpSocket = new RTC::UdpSocket(this, AF_INET);//创建udpsocket
OnPacketRecv()中根据data中不同的类型数据分别接收并处理
OnStunDataRecv();//stun协议数据接收处理
OnRtcpDataRecv();//Rtcp协议数据接收处理
OnRtpDataRecv();//Rtp协议数据接收处理
OnDtlsDataRecv();//Dtls协议数据接收处理
mediasoup类整理
1:mediasoup类简介
类名 | 解释 | 详细介绍 |
Worker | 进程类 | 进程启动,业务入口,主要业务接口 |
Router | 房间类 | 创建消费者,生产者,transport |
Request | 消息类 | 用于接收和发送数据(send) |
Notifier | 通知类 | 用于通知(Emit) |
UnixStreamSocket | 数据传输类 | libuv的上层封装 |
Transport | 通道类 | 将终端与MediaSoup Router连接起来,创建producer和consumer进行传输 |
producer | 生产者类 | ⽣产媒体数据,⾳频或视频 |
consumer | 消费者类 | 消费媒体数据,音频或视频 |
2:主要业务图