MediaSoup流媒体之创建Router和WebRtc的创建生产者底层源码分析

MediaSoup流媒体之创建Router和WebRtc的创建生产者底层源码分析,第1张

MediaSoup流媒体之创建Router和WebRtc的创建生产者底层源码分析

MediaSoup流媒体之创建Router和创建WebRtc生产者底层源码分析
  • MediaSoup流媒体之创建Router和WebRtc的创建生产者底层源码分析
  • 前言
    • 一、 MediaSoup流媒体底层C++的结构
      • 1、 MediaSoup 中Worker、Router、Transport之间的关系
      • 2、 Mediasoup 业务流程图
    • 二、 MediaSoup 创建 Router源码分析
    • 三、 Mediasoup 创建WebRtc传输通道
    • 四、 Mediasoup 连接WebRtc通道
  • 总结


前言

WebRTC 从mediasoup流媒体服务器入手, 会看问题全面一些 。

代码简单易学习

这个是请求关键帧? fir、pli


提示:以下是本篇文章正文内容,下面案例可供参考

一、 MediaSoup流媒体底层C++的结构 1、 MediaSoup 中Worker、Router、Transport之间的关系

每个进程有一个Worker管理 房间(Router)

在房间下面每个生产者和消费者的传输transport (PlainTransport, WebRtcTransport 主要这个两个 )

房间管理每个传输的通道Transport

然后这边C++与js之间通信的C++处理的流程

先在Work找处理方法如果没有找到就到Router类中处理方法去找到方法

伪代码


class Worker
{
	.....
	public:
	void OnChannelRequest(...)
	{
		switch (request->methodId)
		{
			case: 1;
			{
				.....
			}
			....
			// 没有找到方法就到Router类中去找到方法
			default:
			{	
				....
				router->HandleRequest(request);
			}
		}
	}
	....
}

class Router
{
	.....
	public:
	void OnChannelRequest(...)
	{
		switch (request->methodId)
		{
			case: 100;
			{
				.....
			}
			....
			// 没有找到方法就到transport类中去找到方法
			default:
			{	
				....
				transport->HandleRequest(request);
			}
		}
	}
	....
}




2、 Mediasoup 业务流程图

二、 MediaSoup 创建 Router源码分析

就不看 js部分的代码 这边看cpp部分的代码

		case Channel::ChannelRequest::MethodId::WORKER_CREATE_ROUTER:
		{
			std::string routerId;
			try
			{   
				SetNewRouterIdFromInternal(request->internal, routerId);
			}
			catch (const MediaSoupError& error)
			{
				MS_THROW_ERROR("%s [method:%s]", error.buffer, request->method.c_str());
			}

			auto* router = new RTC::Router(routerId);
			// 插入router到map表中 
			this->mapRouters[routerId] = router;

			MS_DEBUG_DEV("Router created [routerId:%s]", routerId.c_str());

			request->Accept();

			break;
		}
三、 Mediasoup 创建WebRtc传输通道
			case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT:
			{
				std::string transportId;

				// This may throw.
				SetNewTransportIdFromInternal(request->internal, transportId);

				// This may throw. 
				auto* webRtcTransport = new RTC::WebRtcTransport(transportId, this, request->data);

				// Insert into the map.
				this->mapTransports[transportId] = webRtcTransport;

				MS_DEBUG_DEV("WebRtcTransport created [transportId:%s]", transportId.c_str());

				json data = json::object();

				webRtcTransport->FillJson(data);

				request->Accept(data);

				break;
			}



// 在WebRtcTransport 构造方法

bool enableUdp{ true };
		auto jsonEnableUdpIt = data.find("enableUdp");

		if (jsonEnableUdpIt != data.end())
		{
			if (!jsonEnableUdpIt->is_boolean())
				MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)");

			enableUdp = jsonEnableUdpIt->get<bool>();
		}

		bool enableTcp{ false };
		auto jsonEnableTcpIt = data.find("enableTcp");

		if (jsonEnableTcpIt != data.end())
		{
			if (!jsonEnableTcpIt->is_boolean())
				MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)");

			enableTcp = jsonEnableTcpIt->get<bool>();
		}

		bool preferUdp{ false };
		auto jsonPreferUdpIt = data.find("preferUdp");

		if (jsonPreferUdpIt != data.end())
		{
			if (!jsonPreferUdpIt->is_boolean())
				MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)");

			preferUdp = jsonPreferUdpIt->get<bool>();
		}

		bool preferTcp{ false };
		auto jsonPreferTcpIt = data.find("preferTcp");

		if (jsonPreferTcpIt != data.end())
		{
			if (!jsonPreferTcpIt->is_boolean())
				MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)");

			preferTcp = jsonPreferTcpIt->get<bool>();
		}

		auto jsonListenIpsIt = data.find("listenIps");

		if (jsonListenIpsIt == data.end())
			MS_THROW_TYPE_ERROR("missing listenIps");
		else if (!jsonListenIpsIt->is_array())
			MS_THROW_TYPE_ERROR("wrong listenIps (not an array)");
		else if (jsonListenIpsIt->empty())
			MS_THROW_TYPE_ERROR("wrong listenIps (empty array)");
		else if (jsonListenIpsIt->size() > 8)
			MS_THROW_TYPE_ERROR("wrong listenIps (too many IPs)");

		std::vector<ListenIp> listenIps(jsonListenIpsIt->size());

		for (size_t i{ 0 }; i < jsonListenIpsIt->size(); ++i)
		{
			auto& jsonListenIp = (*jsonListenIpsIt)[i];
			auto& listenIp     = listenIps[i];

			if (!jsonListenIp.is_object())
				MS_THROW_TYPE_ERROR("wrong listenIp (not an object)");

			auto jsonIpIt = jsonListenIp.find("ip");

			if (jsonIpIt == jsonListenIp.end())
				MS_THROW_TYPE_ERROR("missing listenIp.ip");
			else if (!jsonIpIt->is_string())
				MS_THROW_TYPE_ERROR("wrong listenIp.ip (not an string");

			listenIp.ip.assign(jsonIpIt->get<std::string>());

			// This may throw.
			Utils::IP::NormalizeIp(listenIp.ip);

			auto jsonAnnouncedIpIt = jsonListenIp.find("announcedIp");

			if (jsonAnnouncedIpIt != jsonListenIp.end())
			{
				if (!jsonAnnouncedIpIt->is_string())
					MS_THROW_TYPE_ERROR("wrong listenIp.announcedIp (not an string)");

				listenIp.announcedIp.assign(jsonAnnouncedIpIt->get<std::string>());
			}
		}

		uint16_t port{ 0 };
		auto jsonPortIt = data.find("port");

		if (jsonPortIt != data.end())
		{
			if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt)))
				MS_THROW_TYPE_ERROR("wrong port (not a positive number)");

			port = jsonPortIt->get<uint16_t>();
		}

		try
		{
			uint16_t iceLocalPreferenceDecrement{ 0 };

			if (enableUdp && enableTcp)
				this->iceCandidates.reserve(2 * jsonListenIpsIt->size());
			else
				this->iceCandidates.reserve(jsonListenIpsIt->size());

			for (auto& listenIp : listenIps)
			{
				if (enableUdp)
				{
					// ICE 优先级    就是 从是先开始连接
					uint16_t iceLocalPreference =
					  IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement;

					if (preferUdp)
						iceLocalPreference += 1000;

					uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference);

					// This may throw.
					RTC::UdpSocket* udpSocket;
					// TODO@chensong 这边port 是使用同一个端口吗???
					if (port != 0)
						udpSocket = new RTC::UdpSocket(this, listenIp.ip, port);
					else
						udpSocket = new RTC::UdpSocket(this, listenIp.ip);

					this->udpSockets[udpSocket] = listenIp.announcedIp;

					if (listenIp.announcedIp.empty())
						this->iceCandidates.emplace_back(udpSocket, icePriority);
					else
						this->iceCandidates.emplace_back(udpSocket, icePriority, listenIp.announcedIp);
				}

				if (enableTcp)
				{
					uint16_t iceLocalPreference =
					  IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement;

					if (preferTcp)
						iceLocalPreference += 1000;

					uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference);

					// This may throw.
					RTC::TcpServer* tcpServer;
					if (port != 0)
						tcpServer = new RTC::TcpServer(this, this, listenIp.ip, port);
					else
						tcpServer = new RTC::TcpServer(this, this, listenIp.ip);

					this->tcpServers[tcpServer] = listenIp.announcedIp;

					if (listenIp.announcedIp.empty())
						this->iceCandidates.emplace_back(tcpServer, icePriority);
					else
						this->iceCandidates.emplace_back(tcpServer, icePriority, listenIp.announcedIp);
				}

				// Decrement initial ICE local preference for next IP.
				iceLocalPreferenceDecrement += 100;
			}

			// Create a ICE server.  这边创建ICE 协商    STURN 服务器 *** 作  验证用户合法性   
			// 1. 验证用户名(16)
			// 2. 验证密码 (32)
			this->iceServer = new RTC::IceServer(
			  this, Utils::Crypto::GetRandomString(16), Utils::Crypto::GetRandomString(32));

			// Create a DTLS transport.
			this->dtlsTransport = new RTC::DtlsTransport(this);

四、 Mediasoup 连接WebRtc通道 总结

代码项目地址:https://github.com/chensongpoixs/cmediasoup.git

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/674966.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存