Mediasoup整体流程

目前基于WebRTC的低延时直播很火热,相比较WebRTC对客户端做的标准,服务端的信令媒体并没有严格规范,现在主流的媒体服务器有Licode、Janus、MediaSoup等。Mediasoup作为一个高性能的SFU媒体服务器,代码结构清晰,上手容易,可定制化较强。我接触MediaSoup有挺长一段时间,基于MediaSoup v3.0做过一定的开发优化,计划写个专题,大家可以参考一下。

1. 基本概念

网上关于Mediasoup基础概念的介绍一大堆,这里不再展开写了,给个链接。
https://blog.csdn.net/Dreamandpassion/article/details/107799915

2. MediaSoup框架介绍

原生的MediaSoup分为JS和C++两部分,JS部分属于MediaSoup业务部分,可以根据项目需要进行修改,我对JS理解有限,项目中剔除掉JS部分代码,只保留C++核心代码,根据项目需求用C++重写了JS的部分功能。所以这个专题主要介绍MediaSoup C++部分相关处理。

在这里插入图片描述
MediaSoup使用多进程模型,有一个主应用进程(JS),主要做媒体流的状态管理、Worker进程的管理(包括Worker进程的创建、通信、销毁等)等,Worker进程创建的个数依赖于服务器的CPU核数,有多个少CPU核,就启动多少个Worker进程;Worker进程做流的处理,包括RTP包的收发、带宽评估、丢包重传等,这部分是MediaSoup的核心功能。

这里主要分析下Worker进程收发数据的过程,包括两类:一类是收发应用进程的数据;另一类是收发网络数据。

2.1 收发应用进程数据

2.1.1 初始化过程

应用进程与Worker进程通过SocketPair管道进行通信。每个Worker进程都是基于libuv来做的,是单线程的事件触发机制。当有数据到达时,就会触发libuv的事件,调用预先注册好的回调函数进行处理。初始化流程如下:

1.在Worker进程的main函数中(mediasoup/worker/src/main.cpp),创建Channel::UnixStreamSocket对象,它是libuv对管道的封装。

int main(int argc, char* argv[])
{
   
	// Ensure we are called by our Node library.
	if (!std::getenv("MEDIASOUP_VERSION"))
	{
   
		MS_ERROR_STD("you don't seem to be my real father!");

		std::_Exit(EXIT_FAILURE);
	}
	std::string version = std::getenv("MEDIASOUP_VERSION");

	// Initialize libuv stuff (we need it for the Channel).
	DepLibUV::ClassInit();
	// Channel socket (it will be handled and deleted by the Worker).
	Channel::UnixStreamSocket* channel{
    nullptr };

	// PayloadChannel socket (it will be handled and deleted by the Worker).
	PayloadChannel::UnixStreamSocket* payloadChannel{
    nullptr };

	try
	{
   
		channel = new Channel::UnixStreamSocket(ConsumerChannelFd, ProducerChannelFd);
	}
	catch (const MediaSoupError& error)
	{
   
		MS_ERROR_STD("error creating the Channel: %s", error.what());

		std::_Exit(EXIT_FAILURE);
	}
	
	// ...
}

2.初始化consumerSocket对象和producerSocket对象分别用于与应用进程的数据收发,注意它们的基类是::UnixStreamSocket,它位于全局空间内,与上述Channel::UnixStreamSocket对象是两个对象。

UnixStreamSocket::UnixStreamSocket(int consumerFd, int producerFd)
	  : consumerSocket(consumerFd, NsMessageMaxLen, this), producerSocket(producerFd, NsMessageMaxLen)
{
   
	MS_TRACE_STD();
}

// 只列出consumerSocket初始化,producerSocket初始化类似
ConsumerSocket::ConsumerSocket(int fd, size_t bufferSize, Listener* listener)
	 : ::UnixStreamSocket(fd, bufferSize, ::UnixStreamSocket::Role::CONSUMER), listener(listener)
{
   
	MS_TRACE_STD();
}

UnixStreamSocket::UnixStreamSocket(uv_pipe_t *uvHandle, size_t bufferSize, UnixStreamSocket::Role role)
 : bufferSize(bufferSize), role(role)
{
   
	MS_TRACE_STD();

	this->uvHandle = uvHandle;
	int err;
//	this->uvHandle       = new uv_pipe_t;
	uvHandle->data = static_cast<void*>(this);

	if (this->role == UnixStreamSocket::Role::CONSUMER)
	{
   
		// Start reading.
		err = uv_read_start(
		  reinterpret_cast<uv_stream_t*>(uvHandle),
		  static_cast<uv_alloc_cb>(onAlloc
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值