mediasoup 源码分析 (八)分析PlainTransport

mediasoup 源码分析 (六)分析PlainTransport

        • 一、接收裸RTP流
        • 二、mediasoup 中udp建立过程
    • tips

一、接收裸RTP流

PlainTransport 可以接收裸RTP流,也可以接收AES加密的RTP流。源码中提供了一个通过ffmpeg发送裸RTP流到mediasoup的脚本,具体地址为:mediasoup-demo/broadcasters/ffmpeg.sh
脚本就是通过HTTP Post发送创建PlainTranport请求,然后通过ffmpeg向指定地址+端口,发送RTP流

res=$(${HTTPIE_COMMAND} \
	POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID}/transports \
	type="plain" \
	comedia:=true \
	rtcpMux:=false \
	2> /dev/null)

ffmpeg发送RTP流

#
# NOTES:
# - We can add ?pkt_size=1200 to each rtp:// URI to limit the max packet size
#   to 1200 bytes.
#
ffmpeg \
	-re \
	-v info \
	-stream_loop -1 \
	-i ${MEDIA_FILE} \
	-map 0:a:0 \
	-acodec libopus -ab 128k -ac 2 -ar 48000 \
	-map 0:v:0 \
	-pix_fmt yuv420p -c:v libvpx -b:v 1000k -deadline realtime -cpu-used 4 \
	-f tee \
	"[select=a:f=rtp:ssrc=${AUDIO_SSRC}:payload_type=${AUDIO_PT}]rtp://${audioTransportIp}:${audioTransportPort}?rtcpport=${audioTransportRtcpPort}|[select=v:f=rtp:ssrc=${VIDEO_SSRC}:payload_type=${VIDEO_PT}]rtp://${videoTransportIp}:${videoTransportPort}?rtcpport=${videoTransportRtcpPort}"
二、mediasoup 中udp建立过程

RTP:UdpSocket的构造函数,开启IP绑定

namespace RTC
{
	/* Instance methods. */

	UdpSocket::UdpSocket(Listener* listener, std::string& ip)
	  : // This may throw.
	    ::UdpSocket::UdpSocket(PortManager::BindUdp(ip)), listener(listener)
	{
		MS_TRACE();
	}

真正绑定的地方在PortManager::BindUdp(ip)中,随机从指定Port范围中选出可用Port,然后绑定

// Choose a random port index to start from.
   portIdx = static_cast<size_t>(Utils::Crypto::GetRandomUInt(
   static_cast<uint32_t>(0), static_cast<uint32_t>(ports.size() - 1)));
   .....
   .....
   // Increase current port index.
   portIdx = (portIdx + 1) % ports.size();

   // So the corresponding port is the vector position plus the RTC minimum port.
   port = static_cast<uint16_t>(portIdx + Settings::configuration.rtcMinPort);
   .....
   //udp绑定
   switch (transport)
   {
	  case Transport::UDP:
	  {
		 err = uv_udp_bind(
		 reinterpret_cast<uv_udp_t*>(uvHandle),
		 reinterpret_cast<const struct sockaddr*>(&bindAddr),flags);
      }

三、全局的UdpSocket绑定接收

UdpSocket::UdpSocket(uv_udp_t* uvHandle) : uvHandle(uvHandle)
{
	MS_TRACE();

	int err;

	this->uvHandle->data = static_cast<void*>(this);

	err = uv_udp_recv_start(
	  this->uvHandle, static_cast<uv_alloc_cb>(onAlloc), static_cast<uv_udp_recv_cb>(onRecv)); // 接收回调函数
}


inline static void onRecv(
  uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags)
{
	auto* socket = static_cast<UdpSocket*>(handle->data);

	if (socket)
		socket->OnUvRecv(nread, buf, addr, flags);
}
//然后回调到RTC::UdpSocket::UserOnUdpDatagramReceived的函数
	void UdpSocket::UserOnUdpDatagramReceived(const uint8_t* data, size_t len, const struct sockaddr* addr)
	{
		MS_TRACE();

		if (this->listener == nullptr)
		{
			MS_ERROR("no listener set");

			return;
		}

		// Notify the reader.此处的Listener就是PlainTransport
		this->listener->OnUdpSocketPacketReceived(this, data, len, addr);
	}

//PainTransport接收到数据
	inline void PlainTransport::OnUdpSocketPacketReceived(
	  RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr)
	{
		MS_TRACE();
        //TranportTuple维护socket与客户端地址的关联关系
		RTC::TransportTuple tuple(socket, remoteAddr);

		OnPacketReceived(&tuple, data, len);
	}
//处理接收到的udp包
inline void PlainTransport::OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Increase receive transmission.
		RTC::Transport::DataReceived(len);

		// Check if it's RTCP.
		if (RTC::RTCP::Packet::IsRtcp(data, len))
		{
			OnRtcpDataReceived(tuple, data, len);
		}
		// Check if it's RTP.
		else if (RTC::RtpPacket::IsRtp(data, len))
		{
			OnRtpDataReceived(tuple, data, len);
		}
		// Check if it's SCTP.
		else if (RTC::SctpAssociation::IsSctp(data, len))
		{
			OnSctpDataReceived(tuple, data, len);
		}
		else
		{
			MS_WARN_DEV("ignoring received packet of unknown type");
		}
	}

最后数据传到基类 Transport

Transport处理RTP

tips

更多关于mediasoup的文章可以进入我的专栏查看
http://t.csdnimg.cn/3UQeL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/748422.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

centos上快速搭建zfile文件网站

什么是zfile&#xff1f; zfile文件网站是最方便快捷的在线目录展示程序&#xff0c;支持将本地文件、FTP、SFTP、S3、OneDrive 等存储在网站上展示并浏览&#xff01; 本教程参考&#xff1a; https://docs.zfile.vip/install/os-linux复现 今天的搭建环境是centos7.9 第一…

CPPTest设计分析

目录 1 概述2 设计3 扩展Output3.1 扩展实例 1 概述 CppTest是一个可移植、功能强大但简单的单元测试框架&#xff0c;用于处理C中的自动化测试。重点在于可用性和可扩展性。支持多种输出格式&#xff0c;并且可以轻松添加新的输出格式。 CppTest下载地址Sourceforge Github地…

Java技术栈总结:数据库MySQL篇

一、慢查询 1、常见情形 聚合查询 多表查询 表数据量过大查询 深度分页查询 2、定位慢查询 方案一、开源工具 调试工具&#xff1a;Arthas运维工具&#xff1a;Prometheus、Skywalking 方案二、MySQL自带慢日志 在MySQL配置文件 /etc/my.conf 中配置&#xff1a; # …

云原生技术峰会:引领智能算力时代的创新浪潮

云原生技术峰会&#xff1a;引领智能算力时代的创新浪潮 随着云计算技术的飞速发展和智能算力的不断提升&#xff0c;云原生架构已成为推动企业数字化转型的重要力量。一场汇聚了业界顶尖专家和学者的云原生技术峰会成功举行&#xff0c;与会者共同探讨了云原生在智能算力时代…

python3用两个栈实现一个队列

栈与队列 栈&#xff1a;先入后出&#xff0c;First In First Out (FIFO) &#xff0c;类似桶&#xff08;入到桶底、取从桶顶&#xff09; 队列&#xff1a;先入先出&#xff0c;First In Last Out (FILO) 用两个栈实现一个队列 两个桶&#xff08;栈&#xff09;&#x…

Shell 编程入门

优质博文&#xff1a;IT-BLOG-CN 【1】x.sh文件内容编写&#xff1a; 固定开头&#xff1a;#&#xff01;/bin/sh&#xff1b; 【2】学习的第一个命令就是echo输出的意思&#xff1b; 【3】其实shell脚本也就是在文件中写命令&#xff0c;但是我们要写的是绝对路径&#xff1a…

Web渗透:逻辑越权漏洞

逻辑越权漏洞&#xff08;Business Logic Vulnerability&#xff09;是指攻击者利用应用程序业务逻辑中的漏洞&#xff0c;绕过正常的安全控制&#xff0c;执行未授权的操作。与常见的技术性漏洞不同&#xff0c;逻辑越权漏洞通常与应用程序的功能和流程有关&#xff0c;需要对…

Java初识集合(后续不断补充)

第一次更新时间&#xff1a;2024.6.26 集合概述 Java中的集合就像一个容器&#xff0c;专门用来存储Java对象&#xff08;实际上是对象的引用&#xff0c;但习惯称为对象&#xff09;&#xff0c;这些对象可以是任意的数据类型&#xff0c;并且长度可变。其中&#xff0c;这些…

使用go语言来完成复杂excel表的导出导入

使用go语言来完成复杂excel表的导出导入&#xff08;一&#xff09; 1.复杂表的导入 开发需求是需要在功能页面上开发一个excel文件的导入导出功能&#xff0c;这里的复杂指定是表内数据夹杂着一对多&#xff0c;多对一的形式&#xff0c;如下图所示。数据杂乱而且对应不统一。…

基于单片机和 Arduino 平台的六自由度可控机械手臂

摘 要 : 为了降低机械手臂的设计开发难度 &#xff0c; 并使之尽早地投入应用 &#xff0c; 设计一种基于单片机和 Arduino 平台的六自由度可控机械手臂 。提出六自由度可控机械手臂的控制方案&#xff0c; 给出机械手臂控制系统的结构框图 。 详细设计六自由度可控机械手臂…

1991java Web体检预约管理系统eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP体检预约管理系统是一套完善的web设计系统&#xff0c;对理解JSP java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使用…

2024华为数通HCIP-datacom最新题库(变题更新⑤)

请注意&#xff0c;华为HCIP-Datacom考试831已变题 请注意&#xff0c;华为HCIP-Datacom考试831已变题 请注意&#xff0c;华为HCIP-Datacom考试831已变题 近期打算考HCIP的朋友注意了&#xff0c;如果你准备去考试&#xff0c;还是用的之前的题库&#xff0c;切记暂缓。 1、…

MATLAB-遗传GA-CNN-SVM,基于GA遗传优化算法优化卷积神经网络CNN结合支持向量机SVM数据分类(多特征输入多分类)

MATLAB-遗传GA-CNN-SVM&#xff0c;基于GA遗传优化算法优化卷积神经网络CNN结合支持向量机SVM数据分类(多特征输入多分类) 1.数据均为Excel数据&#xff0c;直接替换数据就可以运行程序。 2.所有程序都经过验证&#xff0c;保证程序可以运行。 3.具有良好的编程习惯&#xf…

linux centos rabbitmq3.7.5 一键安装部署

linux centos rabbitmq3.7.5 一键安装部署 一、基础理论二、kafka和rocketmq、rabbitmq的区别三、下载所需安装包四、一键安装 一、基础理论 RabbitMQ是一个实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息代理软件&#xff0c;其作用主要体现在以下几个方面&a…

Docker 查看源地址/仓库地址,更改

一、源地址文件配置路径。若有docker文件夹&#xff0c;没有json&#xff0c;可以新增&#xff0c;复制进去内容 /etc/docker/daemon.json {"registry-mirrors": ["https://dockerhub.azk8s.cn","https://hub-mirror.c.163.com"&#xff0c;&q…

“北京到底有谁在啊”影视APP开发,解锁最简单的快乐

随着电视剧《玫瑰的故事》在腾讯视频APP热播&#xff0c;APP也增加了很多热度&#xff0c;一款丰富的影视APP&#xff0c;无论是热门大片、经典影视剧、还是最新综艺节目&#xff0c;能畅享无限精彩的影视内容&#xff01; 开发影视APP&#xff0c;需要专业的技术服务商来解决…

k8s手撕架构图+详解

“如果您在解决类似问题时也遇到了困难&#xff0c;希望我的经验分享对您有所帮助。如果您有任何疑问或者想分享您的经历&#xff0c;欢迎在评论区留言&#xff0c;我们可以一起探讨解决方案。祝您在编程路上顺利前行&#xff0c;不断突破技术的难关&#xff0c;感谢您的阅读&a…

使用nvm切换node版本时报错:exit status 1解决办法

作者介绍&#xff1a;计算机专业研究生&#xff0c;现企业打工人&#xff0c;从事Java全栈开发 主要内容&#xff1a;技术学习笔记、Java实战项目、项目问题解决记录、AI、简历模板、简历指导、技术交流、论文交流&#xff08;SCI论文两篇&#xff09; 上点关注下点赞 生活越过…

项目开发 TCP-Socket连接功能实现(Android端)

前段时间在公司做项目的时候遇到了一个功能需要使用TCP-Socket连接硬件设备进行通信&#xff0c;查了很多资料也只是关于HTTP-Socket相关的&#xff0c;没法满足项目的要求&#xff0c;后来查到一个相关的插件&#xff0c;现在有时间和大家分享一下。 项目简单介绍&#xff1a…

基于STM32+华为云IOT设计的智能冰箱(华为云IOT)

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】摘要 1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发 二、部署华为云物联网平台2.1 物联网平台介绍2.2 开通物联网服务2.3 创建产品&#xff08…