精华内容
下载资源
问答
  • E:\ADDEV\RTCTRANS\36tTRANS\36trans_mediasoup\tomkwok-mediasoup-cpp\worker\src\DepLibUV.cpp #define MS_CLASS "DepLibUV" // #define MS_LOG_DEV_LEVEL 3 #include "DepLibUV.hpp" #include "Logger.hpp" #in...

    • 一个 worker 对应一个libuv 实例
    • 一个libuv实例 对应一个loop
    • libuv的静态方法,比如时间,libwebrtc也有用到。因此是核心基础网络库。

    loop 是静态唯一的

    	static uv_loop_t* loop;
    
    • 提供时间:
    	static uint64_t GetTimeUs()
    	{
       
    		return static_cast<uint64_t>(
    展开全文
  • MediaSoup 收包处理流程

    2020-11-27 10:08:02
    //从producer 收到包 ... MS_TRACE(); // May need to create a new RtpStreamRecv. MayNeedNewStream(packet); // Find the corresponding RtpStreamRecv. uint32_t ssrc = packet->GetSsrc(); RTC::Rt.
    //从producer 收到包
    void Producer::ReceiveRtpPacket(RTC::RtpPacket *packet)
    {
      MS_TRACE();
    
      // May need to create a new RtpStreamRecv.
      MayNeedNewStream(packet);
    
      // Find the corresponding RtpStreamRecv.
      uint32_t ssrc = packet->GetSsrc();
      RTC::RtpStreamRecv *rtpStream{nullptr};
      RTC::RtpEncodingParameters::Profile profile;
      std::unique_ptr<RTC::RtpPacket> clonedPacket;
    
      // Media RTP stream found.
      if (this->mapSsrcRtpStreamInfo.find(ssrc) != this->mapSsrcRtpStreamInfo.end())
      {
        rtpStream = this->mapSsrcRtpStreamInfo[ssrc].rtpStream;
    
        auto &info = this->mapSsrcRtpStreamInfo[ssrc];
        rtpStream = info.rtpStream;
        profile = info.profile;
    
        // Let's clone the RTP packet so we can mangle the payload (if needed) and other
        // stuff that would change its size.
    //用一块固定的内存ClonedPacketBuffer clone 一份,clonedPacket为unique_ptr,离开该函数也会自动释放。
        clonedPacket.reset(packet->Clone(ClonedPacketBuffer));
        packet = clonedPacket.get();
        // Process the packet.
        if (!rtpStream->ReceivePacket(packet))//这里调用rtpstreamrecv的方法。
        {
          return;
        }
      }
      else //这块是解rtx的逻辑,先解rtx最外层还原出rtp包,再经过上面同样的逻辑进行处理。
      {
        for (auto &kv : this->mapSsrcRtpStreamInfo)
        {
          auto &info = kv.second;
    
          if (info.rtxSsrc != 0u && info.rtxSsrc == ssrc)
          {
            rtpStream = info.rtpStream;
            profile = info.profile;
    
            // Let's clone the RTP packet so we can mangle the payload (if needed) and
            // other stuff that would change its size.
            clonedPacket.reset(packet->Clone(ClonedPacketBuffer));
            packet = clonedPacket.get();
    
            // Process the packet.
            if (!rtpStream->ReceiveRtxPacket(packet))
            {
              return;
            }
    
            // Packet repaired after applying RTX.
            rtpStream->packetsRepaired++;
            break;
          }
        }
      }
    
      // Not found.
      if (!rtpStream)
      {
        MS_WARN_TAG(rtp,
                    "no RtpStream found for given RTP packet "
                    "[ssrc:%" PRIu32 ", seq:%" PRIu16 "]",
                    ssrc, packet->GetSequenceNumber());
        return;
      }
    
      // If paused stop here.
      if (this->paused)
        return;
    
      // set codec type.
      auto mimeType = rtpStream->GetMimeType();
      auto codecType = mimeType.subtype;
      packet->SetCodec(codecType);
    
      // Apply the Producer codec payload type and extension header mapping before
      // dispatching the packet.
      ApplyRtpMapping(packet);
    
      if (packet->IsKeyFrame())
      {
        MS_DEBUG_TAG(rtp,
                     "key frame received [ssrc:%" PRIu32 ", ts:%" PRIu32 ", "
                     "seq:%" PRIu16 ", profile:%s]",
                     packet->GetSsrc(), packet->GetTimestamp(), packet->GetSequenceNumber(),
                     RTC::RtpEncodingParameters::profile2String[profile].c_str());
        if (this->keyFrameRequestManager)
        {
          this->keyFrameRequestManager->KeyFrameReceived(packet->GetSsrc());
        }
      }
    
      auto idrMarkerHolder_ = idrMarkerHolders_[profile];
      if (!idrMarkerHolder_)
      {
        MS_DEBUG_TAG(rtp, "create idrMarkerHolder for profile:%s]",
                     RTC::RtpEncodingParameters::profile2String[profile].c_str());
        idrMarkerHolder_ = std::make_shared<IDRMarkerHolder>();
        idrMarkerHolders_[profile] = idrMarkerHolder_;
      }
    
      if (idrMarkerHolder_->Hold(packet))
      { // hold marker.
        return;
      }
    
      if (packet->CanBuff())
        this->producerBuffer.ProcessRtpPacket(packet);
      else if (this->kind == RTC::Media::Kind::AUDIO)
        this->producerBuffer.ProcessRtpPacketByFlag(packet);
    
      for (auto &listener : this->listeners)
      {
        listener->OnProducerRtpPacket(this, packet, profile);
      }
    
      // send marker if any
      auto marker = idrMarkerHolder_->MayPopMarker();
      if (marker)
      {
        for (auto &listener : this->listeners)
        {
          listener->OnProducerRtpPacket(this, marker, profile);
        }
      }
    }
    
    bool RtpStreamRecv::ReceivePacket(RTC::RtpPacket *packet)
    {
      MS_TRACE();
    
      // Call the parent method.
      if (!RtpStream::ReceivePacket(packet))//更新收到包的seq,判断合法性。
      {
        MS_WARN_TAG(rtp, "packet discarded");
        return false;
      }
    
      // Calculate Jitter.
      CalculateJitter(packet->GetTimestamp());
    
      // Process the packet at codec level.
      if (packet->GetPayloadType() == GetPayloadType())
      {
        Codecs::ProcessRtpPacket(packet, GetMimeType());//调用Codec的Process方法;
      }
    
      // Pass the packet to the NackGenerator.
      if (this->params.useNack)
        this->nackGenerator->ReceivePacket(packet);
      return true;
    }
    
    //根据codec判断使用谁的Process
    void ProcessRtpPacket(RTC::RtpPacket *packet,
                          const RTC::RtpCodecMimeType &mimeType)
    {
      MS_TRACE();
      switch (mimeType.subtype)
      {
      case RTC::RtpCodecMimeType::Subtype::VP8:
      {
        VP8::ProcessRtpPacket(packet);
        break;
      }
      case RTC::RtpCodecMimeType::Subtype::H264:
      {
        H264::ProcessRtpPacket(packet);
        break;
      }
      default:
      {
        break;
      };
      }
    }
    //H264的处理
    void H264::ProcessRtpPacket(RTC::RtpPacket *packet)
    {
      MS_TRACE();
     
      auto data = packet->GetPayload();
      auto len = packet->GetPayloadLength();
    
      PayloadDescriptor *payloadDescriptor = Parse(data, len);//解析H264Nal
    
      if (!payloadDescriptor) return;
    
      PayloadDescriptorHandler *payloadDescriptorHandler =
          new PayloadDescriptorHandler(payloadDescriptor);
    
      packet->SetPayloadDescriptorHandler(payloadDescriptorHandler);
    }
    
    
    H264::PayloadDescriptor *H264::Parse(uint8_t *data, size_t len)
    {
      MS_TRACE();
    
      if (len < 3)
        return nullptr;
    
      std::unique_ptr<PayloadDescriptor> payloadDescriptor(new PayloadDescriptor());
    
      uint8_t nalType = data[0] & 0x1f;
      //uint8_t nal_ref_idc = data[0] & 0x60>>5;//在这算STAP-A的时候会有问题;
      switch (nalType)
      {
      case 5: // IDR SLICE
      {
        MS_DEBUG_TAG(rtp, "IDR IN SINGLE PACKET");
        payloadDescriptor->has_idr = true;
        break;
      }
      case 7:
      {
        MS_DEBUG_TAG(rtp, "SPS IN SINGLE PACKET");
        payloadDescriptor->has_sps = true;
        break;
      }
      case 8:
      {
        MS_DEBUG_TAG(rtp, "PPS IN SINGLE PACKET");
        payloadDescriptor->has_pps = true;
        break;
      }
      case 24: // STAP-A (one packet, multiple nals, same TS)
      {
        size_t index = 1;
    	nal_ref_idc = 0;
        while (index + 2 < len)
        {
          nalType = data[index + 2] & 0x1f;
    	  //add by wx begin
    	  uint8_t temp_nal_ref_idc = data[index + 2] & 0x60>>5;
    	  nal_ref_idc = temp_nal_ref_idc > nal_ref_idc ? temp_nal_ref_idc : nal_ref_idc;
          //add by wx end
    	  size_t naluSize = data[index] * 256 + data[index + 1];
          switch (nalType)
          {
          case 5: // IDR
            MS_DEBUG_TAG(rtp, "IDR IN STAP-A PACKET");
            payloadDescriptor->has_idr = true;
            break;
          case 7: // SPS
            MS_DEBUG_TAG(rtp, "SPS IN STAP-A PACKET");
            payloadDescriptor->has_sps = true;
            break;
          case 8: // PPS
            MS_DEBUG_TAG(rtp, "PPS IN STAP-A PACKET");
            payloadDescriptor->has_pps = true;
            break;
          default:
            break;
          }
          index += 2;
          index += naluSize;
        }
        break;
      }
      case 28: // FU-A (fragmented nal, one nal multiple packets)
      {
        uint8_t fuHeader = data[1];
        // uint8_t startBit = fuHeader >> 7;
        // uint8_t endBit = fuHeader >> 6;
        nalType = fuHeader & 0x1f;
        switch (nalType)
        {
        case 5:
          MS_DEBUG_TAG(rtp, "IDR IN FU-A PACKET");
          payloadDescriptor->has_idr = true;
          break;
        case 7: // SPS, should not happen
          MS_DEBUG_TAG(rtp, "SPS IN FU-A PACKET");
          payloadDescriptor->has_sps = true;
          break;
        case 8: // PPS, should not happen
          MS_DEBUG_TAG(rtp, "PPS IN FU-A PACKET");
          payloadDescriptor->has_pps = true;
          break;
        default:
          break;
        }
        break;
      }
      default:
      {
        // MS_DEBUG_TAG(rtp, "Unable to handle H264 nal type: %u", nalType);
        break;
      }
      }
      payloadDescriptor->nal_ref_idc_test = nal_ref_idc;
      return payloadDescriptor.release();
    }

     

    展开全文
  • mediaSoup 源码分析-srtp操作

    千次阅读 2019-10-16 11:19:45
    srtp操作还是比较简单的 #srtp sesssion创建 SrtpSession::SrtpSession(Type type, Profile profile, uint8_t* key, size... MS_TRACE(); srtp_policy_t policy; // NOLINT(cppcoreguidelines-pro-type-mem...

    srtp操作还是比较简单的

    #srtp sesssion创建

    
    	SrtpSession::SrtpSession(Type type, Profile profile, uint8_t* key, size_t keyLen)
    	{
    		MS_TRACE();
    
    		srtp_policy_t policy; // NOLINT(cppcoreguidelines-pro-type-member-init)
    
    		// Set all policy fields to 0.
    		std::memset(&policy, 0, sizeof(srtp_policy_t));
    
    		switch (profile)
    		{
    			case Profile::AES_CM_128_HMAC_SHA1_80:
    			{
    				srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    				srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    
    				break;
    			}
    
    			case Profile::AES_CM_128_HMAC_SHA1_32:
    			{
    				srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
    				// NOTE: Must be 80 for RTCP.
    				srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    
    				break;
    			}
    
    			case Profile::AEAD_AES_256_GCM:
    			{
    				srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
    				srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp);
    
    				break;
    			}
    
    			case Profile::AEAD_AES_128_GCM:
    			{
    				srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
    				srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp);
    
    				break;
    			}
    
    			default:
    			{
    				MS_ABORT("unknown SRTP profile");
    			}
    		}
    
    		MS_ASSERT(
    		  (int)keyLen == policy.rtp.cipher_key_len,
    		  "given keyLen does not match policy.rtp.cipher_keyLen");
    
    		switch (type)
    		{
    			case Type::INBOUND:
    				policy.ssrc.type = ssrc_any_inbound;
    				break;
    
    			case Type::OUTBOUND:
    				policy.ssrc.type = ssrc_any_outbound;
    				break;
    		}
    
    		policy.ssrc.value = 0;
    		policy.key        = key;
    		// Required for sending RTP retransmission without RTX.
    		policy.allow_repeat_tx = 1;
    		policy.window_size     = 1024;
    		policy.next            = nullptr;
    
    		// Set the SRTP session.
    		srtp_err_status_t err = srtp_create(&this->session, &policy);
    
    		if (DepLibSRTP::IsError(err))
    			MS_THROW_ERROR("srtp_create() failed: %s", DepLibSRTP::GetErrorString(err));
    	}

    #加解密rtp

    bool SrtpSession::EncryptRtp(const uint8_t** data, size_t* len)
    	{
    		MS_TRACE();
    
    		// Ensure that the resulting SRTP packet fits into the encrypt buffer.
    		if (*len + SRTP_MAX_TRAILER_LEN > EncryptBufferSize)
    		{
    			MS_WARN_TAG(srtp, "cannot encrypt RTP packet, size too big (%zu bytes)", *len);
    
    			return false;
    		}
    
    		std::memcpy(EncryptBuffer, *data, *len);
    
    		srtp_err_status_t err =
    		  srtp_protect(this->session, (void*)EncryptBuffer, reinterpret_cast<int*>(len));
    
    		if (DepLibSRTP::IsError(err))
    		{
    			MS_WARN_TAG(srtp, "srtp_protect() failed: %s", DepLibSRTP::GetErrorString(err));
    
    			return false;
    		}
    
    		// Update the given data pointer.
    		*data = (const uint8_t*)EncryptBuffer;
    
    		return true;
    	}
    
    	bool SrtpSession::DecryptSrtp(const uint8_t* data, size_t* len)
    	{
    		MS_TRACE();
    
    		srtp_err_status_t err = srtp_unprotect(this->session, (void*)data, reinterpret_cast<int*>(len));
    
    		if (DepLibSRTP::IsError(err))
    		{
    			MS_DEBUG_TAG(srtp, "srtp_unprotect() failed: %s", DepLibSRTP::GetErrorString(err));
    
    			return false;
    		}
    
    		return true;
    	}
    

    #加解密rtcp

    
    	bool SrtpSession::EncryptRtcp(const uint8_t** data, size_t* len)
    	{
    		MS_TRACE();
    
    		// Ensure that the resulting SRTCP packet fits into the encrypt buffer.
    		if (*len + SRTP_MAX_TRAILER_LEN > EncryptBufferSize)
    		{
    			MS_WARN_TAG(srtp, "cannot encrypt RTCP packet, size too big (%zu bytes)", *len);
    
    			return false;
    		}
    
    		std::memcpy(EncryptBuffer, *data, *len);
    
    		srtp_err_status_t err =
    		  srtp_protect_rtcp(this->session, (void*)EncryptBuffer, reinterpret_cast<int*>(len));
    
    		if (DepLibSRTP::IsError(err))
    		{
    			MS_WARN_TAG(srtp, "srtp_protect_rtcp() failed: %s", DepLibSRTP::GetErrorString(err));
    
    			return false;
    		}
    
    		// Update the given data pointer.
    		*data = (const uint8_t*)EncryptBuffer;
    
    		return true;
    	}
    
    	bool SrtpSession::DecryptSrtcp(const uint8_t* data, size_t* len)
    	{
    		MS_TRACE();
    
    		srtp_err_status_t err =
    		  srtp_unprotect_rtcp(this->session, (void*)data, reinterpret_cast<int*>(len));
    
    		if (DepLibSRTP::IsError(err))
    		{
    			MS_DEBUG_TAG(srtp, "srtp_unprotect_rtcp() failed: %s", DepLibSRTP::GetErrorString(err));
    
    			return false;
    		}
    
    		return true;
    	}

     

    展开全文
  • docker 部署mediasoup

    2021-09-09 12:55:25
    docker run -p 4443:4443 -p 3000:3000 -p 3001:3001 --name ms -tid lcmftianci/mediasoup:v1 docker exec -ti ms /bin/bash cd server edit config.js 172.17.0.3 to docker host npm start cd app npm ...
    docker run -p 4443:4443 -p 3000:3000 -p 3001:3001 -p 40000-49999:40000-49999 --name ms -tid lcmftianci/mediasoup:v1 
    docker exec -ti ms /bin/bash
    
    
    cd server
    edit config.js 172.17.0.3 to docker host
    
    npm start
    
    
    cd app
    npm start
    
    https://ip:3000
    展开全文
  • mediaSoup源码分析-ICE流程

    千次阅读 2019-10-16 15:06:02
    其实很简单,直接放源码吧 inline void WebRtcTransport::OnStunDataReceived( RTC::TransportTuple* tuple, const uint8_t* data, ... MS_TRACE(); RTC::StunPacket* packet = RTC::StunPacket::Parse(dat...
  • mediasoup v3 API

    2021-02-22 15:21:36
    mediasoup The top-level exported module. const mediasoup = require("mediasoup"); // Or using destructuring assignment. const { types, version, observer, createWorker, ...
  • mediaSoup源码分析-dtls操作

    千次阅读 2019-10-16 11:34:39
    dtls主要用来交换srtp的 #在ICE完成后,开始dtls过程 void WebRtcTransport::... MS_TRACE(); // Do nothing if we have the same local DTLS role as the DTLS transport. // NOTE: local role in...
  • Mediasoup调试技巧

    2021-06-03 15:33:33
    1、worker日志 修改mediasoup-demo/server/config.js文件
  • mediasoup v3 API 学习之一

    千次阅读 2020-07-10 13:30:26
    mediasoup 模块的一些属性 ...var ms = require('mediasoup'); console.log(ms.types); 结果如下: { Worker: [Function: Worker], Router: [Function: Router], Transport: [Function: Transport], WebR
  • Mediasoup(webrtc) Demo搭建及测试

    万次阅读 热门讨论 2019-05-07 15:22:14
    团队大佬有点嫌弃原来p2p方案提供商,准备尝试使用webrtc评估替代...基于技术栈就选以node接口的mediasoup这款开源服务器跑起来熟悉下套路。本文为Mediasoup demo部署说明。 Mediasoup官网:https://mediasoup.orgM...
  • nginx部署mediasoup

    2020-08-29 11:20:05
    = 4.9(CentOS7默认的gcc版本是v4.8.5,mediasoup由于使用了大量c++11特性,要求>= 4.9) Python 2.7.5(3也没问题,不过要注意编译脚本需要的python的命令,对python3做个软链接好了) root权限 1、node.js...
  • mediasoup demo的安装部署 1 下载mediasoup 环境:centos 8 虚拟机 mediasoup-demo是存放在git上的,因此需要使用git下载,下载时可能会出现ssl问题,这里直接去掉ssl验证 git config --global http.sslVerify false...
  • Beautiful Soup Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1912Accepted Submission(s): 391 Problem Description  Coach Pang has a lot...
  • mediasoup sfu 单端口方案设计mediasoup simucast 当前现状mediasoup simucast consumer 实现mediasoup simucast consumer 代码分析 mediasoup simucast 当前现状 webrtc具有Simulcast功能,可以将一个分辨率的流...
  • mediasoup RTT 使用场景

    2021-04-09 22:54:05
    mediasoup RTT计算什么是RTTRTT 两种计算方式发送端RTT计算接收端RTT计算RTT 使用场景发送端RTP包重传次数控制接收端NACK发送次数控制 什么是RTT RTT 两种计算方式 发送端RTT计算 接收端RTT计算 RTT 使用场景 发送端...
  • mediasoup是一款轻量级的webrtc系统,官网https://mediasoup.org,github源码下载:https://github.com/versatica/mediasoup 本次测试,系统为ubuntu v18.04.64,使用npm直接安装mediasoup软件,安装过程中踩了一些...
  • 目录 stun介绍 stun 协议分析 属性消息 ...stun 即:Session Traversal ...对于mediasoup和srs等webrtc服务器,本身实现了ice-lite,不需要单独部署stun服务,只需要响应客户端发送的stun request就表明连接.
  • mediasoup 音量监控

    2020-08-04 22:33:09
    需要提供统计间隔internal(250-5000ms),音量阈值threshold(-127-0ms)参数和最大统计个数maxEntries。 AudioLevelObserver 接收producer帧的时候,会统计当前producer音频帧的个数和音量值的统计。然后定时计算...
  • 基于mediasoup 分析dtls ssl 中的BIO 处理收到的DTLS数据,得到私钥 基于获得的私钥key创建srtp DTLS 协议介绍 DTLS(Datagram Transport Layer Security)数据包传输层安全协议。TLS不能保证UDP传输的安全性,...
  • mediasoup中nack的调用机制 1 NACK作用 NACK是用来进行丢包重传的一种方式,简单的理解就是在丢包的时候会根据包序号进行重传,重传的规则可以是遇到丢包时触发,或者定时触发,这里通过mediasoup源码的话分析定时...
  • // Max delay in ms we allow for the stream when switching. // https://en.wikipedia.org/wiki/Audio-to-video_synchronization#Recommendations static const uint32_t MaxExtraOffsetMs{ 75u }; ...
  • MS_TRACE(); uint64_t nowMs = DepLibUV::GetTimeMs(); std::vector<uint16_t> nackBatch; auto it = this->nackList.begin(); while (it != this->nackList.end()) { NackInfo& ...
  • 源码中提供了一个通过ffmpeg发送裸RTP流到mediasoup的脚本,具体地址为:mediasoup-demo/broadcasters/ffmpeg.sh 脚本就是通过HTTP Post发送创建PlainTranport请求,然后通过ffmpeg向指定地址+端口,发送RTP流 ...
  • MediaSoup源码分析之rtp数据的流转 1.概要 mediasoup中的rtp数据流向大概为: 推流客户端–》router–》producer–》consumer–》发送到观看客户端 这里就涉及问题,如何在router中将producer与consumer关联在一起,...
  • 开源的网络事件库有很多种,大家最熟悉的莫过于...mediasoup中,libuv使用由以下两个函数启动,ClassInit负责生成uv_loop_t对象,并初始化相关对象,类似nginx的ngx_worker_process_cycle,RunLoop调用uv_run,启动循
  • MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn= 1000100 ; const int INF=1e9+ 10 ; int n,m; struct Edge { int u,v,w; friend bool ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,176
精华内容 470
关键字:

ms_soup