mediasoup Transport详解与代码实现

mediasoup的Transport体系是连接WebRTC客户端与服务器媒体处理核心的桥梁。基于其通信框架,Transport负责管理网络连接、传输协议以及数据流转发。以下是各Transport类型的结构化整理,包含其核心功能、适用场景及关键代码实现。

一、Transport体系架构概览

mediasoup的Transport继承体系采用分层设计,
所有Transport都继承自基类RTC::Transport::Transport,共享以下核心能力:

  • 生产者/消费者管理 :维护ProducerConsumer的映射表
  • RTP/RTCP处理:提供数据包收发的基础接口
  • 状态管理:跟踪传输连接状态
  • 统计信息收集:收集字节数、数据包数等指标

二、WebRtcTransport:WebRTC标准传输

2.1 功能特性

  • 完整WebRTC协议栈:集成ICE、DTLS、SRTP、SCTP
  • NAT穿透:支持STUN和TURN服务器
  • 双栈支持:同时监听UDP和TCP端口
  • 端口聚合:可通过WebRtcServer共享端口资源

2.2 核心代码实现

2.2.1 构造函数与Socket创建

cpp 复制代码
// 构造函数逻辑
WebRtcTransport::WebRtcTransport(
    RTC::Shared* shared,
    const std::string& id,
    RTC::Transport::Listener* listener,
    const FBS::WebRtcTransport::WebRtcTransportOptions* options)
    : RTC::Transport::Transport(shared, id, listener, options->base())
{
    // 检查是否使用WebRtcServer
    if (options->webRtcServerId())
    {
        // 从shared中查找WebRtcServer
        this->webRtcServer = shared->GetWebRtcServer(options->webRtcServerId()->str());
        if (!this->webRtcServer)
            MS_THROW_ERROR("WebRtcServer not found");
        
        // 注册到WebRtcServer
        this->webRtcServer->AddWebRtcTransport(this);
    }
    else
    {
        // 独立创建Socket(逻辑与WebRtcServer类似)
        const auto* listenInfos = options->listenInfos();
        for (const auto* listenInfo : *listenInfos)
        {
            if (listenInfo->protocol() == FBS::Transport::Protocol::UDP)
            {
                // 创建UdpSocket
                this->udpSocket = new RTC::UdpSocket(
                    this,
                    listenInfo->ip()->str(),
                    listenInfo->port(),
                    listenInfo->flags());
            }
            else if (listenInfo->protocol() == FBS::Transport::Protocol::TCP)
            {
                // 创建TcpServer
                this->tcpServer = new RTC::TcpServer(
                    this,
                    this,
                    listenInfo->ip()->str(),
                    listenInfo->port(),
                    listenInfo->flags());
            }
        }
    }
    
    // 创建ICE和DTLS组件
    this->iceServer = new RTC::IceServer(this, options->iceParameters());
    this->dtlsTransport = new RTC::DtlsTransport(this, options->dtlsParameters());
}

2.2.2 数据接收流程

cpp 复制代码
// UDP数据接收(WebRtcServer转发或直接接收)
void WebRtcTransport::OnUdpSocketPacketReceived(
    RTC::UdpSocket* socket,
    const uint8_t* data,
    size_t len,
    const struct sockaddr* remoteAddr)
{
    // 创建TransportTuple标识连接
    RTC::TransportTuple tuple(socket, remoteAddr);
    
    // 检查是否是STUN报文
    if (RTC::StunPacket::IsStun(data, len))
    {
        // 处理ICE连接检查
        this->iceServer->ProcessStunPacket(&tuple, data, len);
    }
    // 检查是否是DTLS报文
    else if (RTC::DtlsTransport::IsDtls(data, len))
    {
        // 转发到DTLS层处理
        this->dtlsTransport->ProcessDtlsData(data, len, &tuple);
    }
    // 检查是否是RTP/RTCP报文
    else if (RTC::RtpPacket::IsRtp(data, len) || RTC::RtcpPacket::IsRtcp(data, len))
    {
        // 检查SRTP解密会话是否已建立
        if (this->srtpRecvSession)
        {
            // 解密并处理RTP/RTCP
            this->HandleRtpOrRtcpPacket(data, len, &tuple);
        }
    }
}

// TCP连接处理
void WebRtcTransport::OnTcpConnectionClosed(
    RTC::TcpConnection* connection)
{
    // 查找并清理对应的TransportTuple
    auto it = this->tupleTcpConnections.find(connection);
    if (it != this->tupleTcpConnections.end())
    {
        RTC::TransportTuple* tuple = it->second;
        // 清理ICE和DTLS状态
        this->iceServer->RemoveTuple(tuple);
        this->dtlsTransport->RemoveTuple(tuple);
        delete tuple;
        this->tupleTcpConnections.erase(it);
    }
}

三、PlainTransport:简单协议传输

3.1 功能特性

  • 轻量级协议:支持UDP、TCP(可选)
  • 无加密传输:可选SRTP加密
  • COMEDIA模式:支持反向连接(客户端连接服务器)
  • 第三方集成:专为FFmpeg、GStreamer等工具设计

3.2 核心代码实现

3.2.1 构造函数与配置

cpp 复制代码
PlainTransport::PlainTransport(
    RTC::Shared* shared,
    const std::string& id,
    RTC::Transport::Listener* listener,
    const FBS::PlainTransport::PlainTransportOptions* options)
    : RTC::Transport::Transport(shared, id, listener, options->base())
{
    // 解析配置选项
    this->comedia = options->comedia();
    this->rtcpMux = options->rtcpMux();
    
    // 创建UDP Socket(支持端口范围)
    const auto* listenInfo = options->listenInfo();
    if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0)
    {
        uint64_t portRangeHash = 0u;
        this->udpSocket = new RTC::UdpSocket(
            this,
            listenInfo->ip()->str(),
            listenInfo->portRange()->min(),
            listenInfo->portRange()->max(),
            listenInfo->flags(),
            portRangeHash);
    }
    else
    {
        this->udpSocket = new RTC::UdpSocket(
            this,
            listenInfo->ip()->str(),
            listenInfo->port(),
            listenInfo->flags());
    }
    
    // 配置SRTP(如果启用)
    if (options->srtpParameters())
    {
        this->srtpSendSession = new RTC::SrtpSession(
            RTC::SrtpSession::Type::OUTBOUND,
            options->srtpParameters()->cryptoSuite()->str(),
            options->srtpParameters()->keyBase64()->str());
            
        this->srtpRecvSession = new RTC::SrtpSession(
            RTC::SrtpSession::Type::INBOUND,
            options->srtpParameters()->cryptoSuite()->str(),
            options->srtpParameters()->keyBase64()->str());
    }
}

3.2.2 COMEDIA模式处理

cpp 复制代码
// COMEDIA模式:等待客户端连接
void PlainTransport::OnUdpSocketPacketReceived(
    RTC::UdpSocket* socket,
    const uint8_t* data,
    size_t len,
    const struct sockaddr* remoteAddr)
{
    // 创建tuple标识
    RTC::TransportTuple tuple(socket, remoteAddr);
    
    // 如果是COMEDIA模式且尚未建立连接
    if (this->comedia && !this->tuple)
    {
        // 保存第一个连接的客户端地址
        this->tuple = new RTC::TransportTuple(tuple);
        
        // 通知监听者连接已建立
        this->listener->OnPlainTransportConnected(this);
    }
    
    // 检查tuple是否匹配
    if (this->tuple && *this->tuple == tuple)
    {
        // 处理数据包
        this->HandleIncomingPacket(data, len);
    }
}

// 数据包处理
void PlainTransport::HandleIncomingPacket(const uint8_t* data, size_t len)
{
    // 检查是否是RTP/RTCP
    if (RTC::RtpPacket::IsRtp(data, len))
    {
        if (this->srtpRecvSession)
        {
            // SRTP解密
            size_t decryptedLen = len;
            if (!this->srtpRecvSession->DecryptSrtp(
                const_cast<uint8_t*>(data), &decryptedLen))
            {
                MS_WARN_TAG(plain_transport, "SRTP解密失败");
                return;
            }
        }
        
        // 创建RTP包并分发
        auto* packet = RTC::RtpPacket::Parse(data, len);
        if (packet)
        {
            this->ReceiveRtpPacket(packet);
            delete packet;
        }
    }
    else if (RTC::RtcpPacket::IsRtcp(data, len))
    {
        // RTCP处理逻辑类似
        this->ReceiveRtcpPacket(data, len);
    }
}

四、PipeTransport:路由器间传输

4.1 功能特性

  • 路由器级联:连接同一主机或不同主机的Router实例
  • UDP专有:仅支持UDP协议
  • 元数据传递:支持携带Producer/Consumer ID等元数据
  • 高效转发:避免不必要的编码/解码

4.2 核心代码实现

4.2.1 数据包封装格式

cpp 复制代码
// PipeTransport数据包头部结构
struct PipePacketHeader
{
    uint8_t version;          // 协议版本
    uint8_t packetType;       // 包类型:RTP、RTCP、通知等
    uint16_t payloadLength;   // 有效载荷长度
    uint32_t routerId;        // 源路由器ID
    uint32_t producerId;      // 生产者ID(可选)
    uint32_t consumerId;      // 消费者ID(可选)
    uint64_t timestamp;       // 时间戳
    // 后续为实际RTP/RTCP数据
};

// 数据包类型枚举
enum PipePacketType : uint8_t
{
    RTP = 0x01,
    RTCP = 0x02,
    PRODUCER_CLOSED = 0x10,
    CONSUMER_PAUSED = 0x11,
    CONSUMER_RESUMED = 0x12
};

4.2.2 数据发送逻辑

cpp 复制代码
void PipeTransport::SendRtpPacket(
    RTC::RtpPacket* packet,
    RTC::Transport::Consumer* consumer)
{
    // 构建PipeTransport头部
    const size_t headerSize = sizeof(PipePacketHeader);
    const size_t packetSize = headerSize + packet->GetSize();
    
    uint8_t* buffer = new uint8_t[packetSize];
    PipePacketHeader* header = reinterpret_cast<PipePacketHeader*>(buffer);
    
    // 填充头部信息
    header->version = 1;
    header->packetType = PipePacketType::RTP;
    header->payloadLength = static_cast<uint16_t>(packet->GetSize());
    header->routerId = this->router->GetId();
    
    if (consumer)
    {
        header->consumerId = consumer->id;
    }
    
    header->timestamp = uv_hrtime(); // 高精度时间戳
    
    // 拷贝RTP数据
    std::memcpy(buffer + headerSize, packet->GetData(), packet->GetSize());
    
    // 通过UDP Socket发送
    if (this->udpSocket && this->remoteAddr)
    {
        this->udpSocket->Send(buffer, packetSize, this->remoteAddr);
    }
    
    delete[] buffer;
}

// 数据接收处理
void PipeTransport::OnUdpSocketPacketReceived(
    RTC::UdpSocket* socket,
    const uint8_t* data,
    size_t len,
    const struct sockaddr* remoteAddr)
{
    // 验证数据包长度
    if (len < sizeof(PipePacketHeader))
        return;
    
    const PipePacketHeader* header = reinterpret_cast<const PipePacketHeader*>(data);
    
    // 验证协议版本
    if (header->version != 1)
        return;
    
    // 根据包类型处理
    switch (header->packetType)
    {
        case PipePacketType::RTP:
        {
            // 提取RTP数据
            const uint8_t* rtpData = data + sizeof(PipePacketHeader);
            size_t rtpLen = header->payloadLength;
            
            // 解析RTP包
            auto* packet = RTC::RtpPacket::Parse(rtpData, rtpLen);
            if (packet)
            {
                // 根据consumerId查找目标Consumer
                if (header->consumerId != 0)
                {
                    auto* consumer = this->GetConsumerById(header->consumerId);
                    if (consumer)
                    {
                        consumer->ReceiveRtpPacket(packet);
                    }
                }
                delete packet;
            }
            break;
        }
        
        case PipePacketType::PRODUCER_CLOSED:
            // 处理Producer关闭通知
            this->HandleProducerClosed(header->producerId);
            break;
            
        // 其他包类型处理...
    }
}

五、Transport对比与应用场景

特性 WebRtcTransport PlainTransport PipeTransport
协议支持 UDP/TCP + ICE/DTLS/SRTP/SCTP UDP (TCP可选) + 可选SRTP UDP only
加密 强制DTLS-SRTP 可选SRTP 无加密
NAT穿透 完整ICE支持
使用场景 WebRTC客户端连接 第三方媒体工具集成 路由器间级联
复杂度
延迟 较高(协议开销) 最低
数据示例 {type: "webrtc", iceParameters: {...}, dtlsParameters: {...}} {type: "plain", comedia: true, rtcpMux: false} {type: "pipe", listenIp: "127.0.0.1", port: 5000}

六、实际应用示例

6.1 Node.js API使用

javascript 复制代码
// 创建WebRtcTransport
const webRtcTransport = await router.createWebRtcTransport({
    listenIps: [{ ip: "0.0.0.0", announcedIp: "192.168.1.100" }],
    enableUdp: true,
    enableTcp: true,
    preferUdp: true,
    initialAvailableOutgoingBitrate: 1000000
});

// 创建PlainTransport(用于FFmpeg推流)
const plainTransport = await router.createPlainTransport({
    listenIp: { ip: "0.0.0.0", announcedIp: "192.168.1.100" },
    rtcpMux: false,
    comedia: true  // 等待FFmpeg连接
});

// 创建PipeTransport(连接两个Router)
const pipeTransport = await router1.createPipeTransport({
    listenIp: { ip: "127.0.0.1", announcedIp: null },
    port: 5000
});

// 连接到另一个Router
await pipeTransport.connect({
    ip: "127.0.0.1",
    port: 5001,
    routerId: router2.id
});

6.2 性能优化建议

  1. 缓冲区管理
cpp 复制代码
// 使用预分配缓冲区池减少内存分配
class BufferPool {
public:
    BufferPool(size_t bufferSize, size_t poolSize) {
        for (size_t i = 0; i < poolSize; ++i) {
            buffers_.push(new uint8_t[bufferSize]);
        }
    }
    
    uint8_t* Acquire() {
        std::lock_guard<std::mutex> lock(mutex_);
        if (buffers_.empty()) {
            return new uint8_t[bufferSize_];
        }
        uint8_t* buf = buffers_.front();
        buffers_.pop();

----

## 参考来源
- [深入浅出mediasoup---通信框架](https://blog.csdn.net/zhh157/article/details/140577410)
相关推荐
Fisher3Star18 小时前
mediasoup中Node.js与Worker进程通信机制
网络·webrtc
911hzh2 天前
Flutter WebRTC iOS 原理解析:从 getUserMedia 到 Texture,讲清视频采集、纹理渲染与远端通话链路
flutter·ios·webrtc
shao9185162 天前
第12章Streaming(下):视频应用(1)——项目八:基于WebRTC+YOLO的实时目标检测
yolo·目标检测·webrtc·gradio·视频流·yolov10·流式传输
三十_2 天前
WebRTC 远端画面无法显示:ICE 与 SDP 时序问题深度解析与解决方案
webrtc
metaRTC5 天前
metaRTC8 成功适配 RTOS:开启 MCU/嵌入式实时音视频新时代
单片机·嵌入式硬件·webrtc·实时音视频·rtos
Fisher3Star5 天前
mediasoup中ip与announceAddress配置要点
webrtc·sdp
小柯博客6 天前
Amazon Kinesis Video Streams C WebRTC SDK 开发实战
c语言·开发语言·网络·stm32·嵌入式硬件·webrtc·yocto
RTC老炮7 天前
WebRTC下FlexFEC算法架构及原理
网络·算法·音视频·webrtc
换个昵称都难8 天前
webrtc源码下载(2026年4月)
webrtc