Janus客户端修改WebRTC源码支持会议室功能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/twoconk/article/details/81320197

Janus客户端使用最新版本的WebRTC的so,发现subscribe组时,不能看到火狐客户端推送的视频

分析日志,原因是接收rtp包的receiver的sink中没有被注册任何接受者,所以解码后的数据帧没有被回调到应用层。

经过分析,刚开始以为是mid不一致所致,后来发现,是底层库对sendonly做了特殊处理:

火狐的SDP:mid为video字符串


a=group:BUNDLE video


a=msid-semantic: WMS janus


m=video 9 UDP/TLS/RTP/SAVPF 96


c=IN IP4 11.12.115.200


a=sendonly


a=mid:video


a=rtcp-mux

Webrtc中生成的SDP:mid则为0


a=group:BUNDLE 0 1


a=msid-semantic: WMS ARDAMS


m=video 9 UDP/TLS/RTP/SAVPF 127 97 98 99 100 101 125 103 104


c=IN IP4 0.0.0.0


a=rtcp:9 IN IP4 0.0.0.0


a=ice-ufrag:sOgE


a=ice-pwd:OAEMHfMMr26hgYbs70QwRuVT


a=ice-options:trickle renomination

a=mid:0

而WebRTC库中创建Peerconnection对象时,会预先创建一个transceiver(sender和receiver),但mid默认为0

修改前的代码:

RTCErrorOr<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
PeerConnection::AssociateTransceiver(cricket::ContentSource source,
                                     SdpType type,
                                     size_t mline_index,
                                     const ContentInfo& content,
                                     const ContentInfo* old_local_content,
                                     const ContentInfo* old_remote_content)
{
//...
 if (source == cricket::CS_LOCAL) {
    // Find the RtpTransceiver that corresponds to this m= section, using the
    // mapping between transceivers and m= section indices established when
    // creating the offer.
    if (!transceiver) { 
      transceiver = GetTransceiverByMLineIndex(mline_index);
    }
    if (!transceiver) {
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                           "Unknown transceiver");
    }
  } else {
    RTC_DCHECK_EQ(source, cricket::CS_REMOTE);
    // If the m= section is sendrecv or recvonly, and there are RtpTransceivers
    // of the same type...
    if (!transceiver  
        RtpTransceiverDirectionHasRecv(media_desc->direction())) {
	  RTC_LOG(LS_INFO) << "continue find=" << media_desc->direction();
      transceiver = FindAvailableTransceiverToReceive(media_desc->type()); 
    }
    // If no RtpTransceiver was found in the previous step, create one with a
    // recvonly direction.
    if (!transceiver) {
      RTC_LOG(LS_INFO) << "Adding "
                       << cricket::MediaTypeToString(media_desc->type())
                       << " transceiver for MID=" << content.name
                       << " at i=" << mline_index
                       << " in response to the remote description.";
      auto sender =
          CreateSender(media_desc->type(), nullptr, {rtc::CreateRandomUuid()});
      std::string receiver_id;
      if (!media_desc->streams().empty()) {
        receiver_id = media_desc->streams()[0].id;
      } else {
        receiver_id = rtc::CreateRandomUuid();
      }
      auto receiver = CreateReceiver(media_desc->type(), receiver_id);
      transceiver = CreateAndAddTransceiver(sender, receiver);
      transceiver->internal()->set_direction(
          RtpTransceiverDirection::kRecvOnly);
    }

}

rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
PeerConnection::GetAssociatedTransceiver(const std::string& mid) const {
  RTC_DCHECK(IsUnifiedPlan());
  for (auto transceiver : transceivers_) {
  	
	RTC_LOG(LS_INFO) << ", mid:" << mid;
    if (transceiver->mid() == mid) {
      return transceiver;
    }
  }
  RTC_LOG(LS_INFO) << "GetAssociatedTransceiver is null, mid:" << mid;
  return nullptr;
}

修改后的代码:

RTCErrorOr<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
PeerConnection::AssociateTransceiver(cricket::ContentSource source,
                                     SdpType type,
                                     size_t mline_index,
                                     const ContentInfo& content,
                                     const ContentInfo* old_local_content,
                                     const ContentInfo* old_remote_content)
{
//...

  const MediaContentDescription* media_desc = content.media_description();
  auto transceiver = GetAssociatedTransceiver(content.name);
  if (source == cricket::CS_LOCAL) {
    // Find the RtpTransceiver that corresponds to this m= section, using the
    // mapping between transceivers and m= section indices established when
    // creating the offer.
    if (!transceiver) { 
      transceiver = GetTransceiverByMLineIndex(mline_index);
    }
    if (!transceiver) {
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                           "Unknown transceiver");
    }
  } else {
    RTC_DCHECK_EQ(source, cricket::CS_REMOTE);
    // If the m= section is sendrecv or recvonly, and there are RtpTransceivers
    // of the same type...

    //modify start.
    if (!transceiver) {
	  RTC_LOG(LS_INFO) << "continue find=" << media_desc->direction();
      transceiver = FindAvailableTransceiverToReceive(media_desc->type());

      //remote sendonly ,so the client is recvonly
	  if (!RtpTransceiverDirectionHasRecv(media_desc->direction())) {
	      transceiver->internal()->set_direction(
	          RtpTransceiverDirection::kRecvOnly);
	  } 
    }
    //modify end.

    // If no RtpTransceiver was found in the previous step, create one with a
    // recvonly direction.
    if (!transceiver) {
      RTC_LOG(LS_INFO) << "Adding "
                       << cricket::MediaTypeToString(media_desc->type())
                       << " transceiver for MID=" << content.name
                       << " at i=" << mline_index
                       << " in response to the remote description.";
      auto sender =
          CreateSender(media_desc->type(), nullptr, {rtc::CreateRandomUuid()});
      std::string receiver_id;
      if (!media_desc->streams().empty()) {
        receiver_id = media_desc->streams()[0].id;
      } else {
        receiver_id = rtc::CreateRandomUuid();
      }
      auto receiver = CreateReceiver(media_desc->type(), receiver_id);
      transceiver = CreateAndAddTransceiver(sender, receiver);
      transceiver->internal()->set_direction(
          RtpTransceiverDirection::kRecvOnly);
    }
  }




}

猜你喜欢

转载自blog.csdn.net/twoconk/article/details/81320197