mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	[fix] fix capabilities negotiation
This commit is contained in:
		| @@ -160,6 +160,7 @@ | ||||
| class RtpPacket { | ||||
|  public: | ||||
|   typedef enum { | ||||
|     UNDEFINED = 0, | ||||
|     H264 = 96, | ||||
|     H264_FEC_SOURCE = 97, | ||||
|     H264_FEC_REPAIR = 98, | ||||
|   | ||||
| @@ -44,8 +44,9 @@ int IceTransmission::SetLocalCapabilities( | ||||
|   use_reliable_ice_ = use_reliable_ice; | ||||
|   enable_turn_ = force_turn; | ||||
|   force_turn_ = force_turn; | ||||
|   video_payload_types_ = video_payload_types; | ||||
|   audio_payload_types_ = audio_payload_types; | ||||
|   support_video_payload_types_ = video_payload_types; | ||||
|   support_audio_payload_types_ = audio_payload_types; | ||||
|   support_data_payload_types_ = {RtpPacket::PAYLOAD_TYPE::DATA}; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -382,6 +383,11 @@ int IceTransmission::GatherCandidates() { | ||||
|  | ||||
| int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) { | ||||
|   std::string media_stream_sdp = GetRemoteCapabilities(remote_sdp); | ||||
|   if (media_stream_sdp.empty()) { | ||||
|     LOG_ERROR("Set remote sdp failed due to negotiation failed"); | ||||
|     return -1; | ||||
|   } | ||||
|  | ||||
|   ice_agent_->SetRemoteSdp(media_stream_sdp.c_str()); | ||||
|   // LOG_INFO("[{}] set remote sdp", user_id_); | ||||
|  | ||||
| @@ -391,7 +397,7 @@ int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) { | ||||
|  | ||||
| int IceTransmission::SendOffer() { | ||||
|   local_sdp_ = ice_agent_->GenerateLocalSdp(); | ||||
|   AppendLocalCapabilities(local_sdp_); | ||||
|   AppendLocalCapabilitiesToOffer(local_sdp_); | ||||
|   json message = {{"type", "offer"}, | ||||
|                   {"transmission_id", transmission_id_}, | ||||
|                   {"user_id", user_id_}, | ||||
| @@ -407,7 +413,7 @@ int IceTransmission::SendOffer() { | ||||
|  | ||||
| int IceTransmission::SendAnswer() { | ||||
|   local_sdp_ = ice_agent_->GenerateLocalSdp(); | ||||
|   AppendLocalCapabilities(local_sdp_); | ||||
|   AppendLocalCapabilitiesToAnswer(local_sdp_); | ||||
|   json message = {{"type", "answer"}, | ||||
|                   {"transmission_id", transmission_id_}, | ||||
|                   {"user_id", user_id_}, | ||||
| @@ -422,10 +428,11 @@ int IceTransmission::SendAnswer() { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::AppendLocalCapabilities(std::string &remote_sdp) { | ||||
| int IceTransmission::AppendLocalCapabilitiesToOffer( | ||||
|     const std::string &remote_sdp) { | ||||
|   std::string preferred_video_pt; | ||||
|   std::string to_replace = "ICE/SDP"; | ||||
|   std::string video_capabilities; | ||||
|   std::string video_capabilities = "UDP/TLS/RTP/SAVPF"; | ||||
|   std::string audio_capabilities = "UDP/TLS/RTP/SAVPF 111"; | ||||
|   std::string data_capabilities = "UDP/TLS/RTP/SAVPF 127"; | ||||
|  | ||||
| @@ -479,6 +486,51 @@ int IceTransmission::AppendLocalCapabilities(std::string &remote_sdp) { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::AppendLocalCapabilitiesToAnswer( | ||||
|     const std::string &remote_sdp) { | ||||
|   std::string negotiated_video_pt; | ||||
|   std::string negotiated_audio_pt; | ||||
|   std::string negotiated_data_pt; | ||||
|   std::string to_replace = "ICE/SDP"; | ||||
|   std::string protocol = "UDP/TLS/RTP/SAVPF "; | ||||
|   negotiated_video_pt = protocol + std::to_string(negotiated_video_pt_); | ||||
|   negotiated_audio_pt = protocol + std::to_string(negotiated_audio_pt_); | ||||
|   negotiated_data_pt = protocol + std::to_string(negotiated_data_pt_); | ||||
|  | ||||
|   std::size_t video_start = remote_sdp.find("m=video"); | ||||
|   std::size_t video_end = remote_sdp.find("\n", video_start); | ||||
|  | ||||
|   size_t pos = 0; | ||||
|   if (video_start != std::string::npos && video_end != std::string::npos) { | ||||
|     if ((pos = local_sdp_.find(to_replace, video_start)) != std::string::npos) { | ||||
|       local_sdp_.replace(pos, to_replace.length(), negotiated_video_pt); | ||||
|       pos += negotiated_video_pt.length(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   std::size_t audio_start = remote_sdp.find("m=audio"); | ||||
|   std::size_t audio_end = remote_sdp.find("\n", audio_start); | ||||
|  | ||||
|   if (audio_start != std::string::npos && audio_end != std::string::npos) { | ||||
|     if ((pos = local_sdp_.find(to_replace, audio_start)) != std::string::npos) { | ||||
|       local_sdp_.replace(pos, to_replace.length(), negotiated_audio_pt); | ||||
|       pos += negotiated_audio_pt.length(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   std::size_t data_start = remote_sdp.find("m=data"); | ||||
|   std::size_t data_end = remote_sdp.find("\n", data_start); | ||||
|  | ||||
|   if (data_start != std::string::npos && data_end != std::string::npos) { | ||||
|     if ((pos = local_sdp_.find(to_replace, data_start)) != std::string::npos) { | ||||
|       local_sdp_.replace(pos, to_replace.length(), negotiated_data_pt); | ||||
|       pos += negotiated_data_pt.length(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| std::string IceTransmission::GetRemoteCapabilities( | ||||
|     const std::string &remote_sdp) { | ||||
|   std::string media_stream_sdp; | ||||
| @@ -491,9 +543,18 @@ std::string IceTransmission::GetRemoteCapabilities( | ||||
|   std::size_t candidate_start = data_end; | ||||
|  | ||||
|   if (!remote_capabilities_got_) { | ||||
|     GetAceptedVideoPayloadType(remote_sdp); | ||||
|     GetAceptedAudioPayloadType(remote_sdp); | ||||
|     GetAceptedDataPayloadType(remote_sdp); | ||||
|     if (NegotiateVideoPayloadType(remote_sdp)) { | ||||
|       remote_capabilities_got_ = true; | ||||
|       return std::string(); | ||||
|     } | ||||
|     if (NegotiateAudioPayloadType(remote_sdp)) { | ||||
|       remote_capabilities_got_ = true; | ||||
|       return std::string(); | ||||
|     } | ||||
|     if (NegotiateDataPayloadType(remote_sdp)) { | ||||
|       remote_capabilities_got_ = true; | ||||
|       return std::string(); | ||||
|     } | ||||
|     remote_capabilities_got_ = true; | ||||
|   } | ||||
|  | ||||
| @@ -521,12 +582,7 @@ std::string IceTransmission::GetRemoteCapabilities( | ||||
|   return media_stream_sdp; | ||||
| } | ||||
|  | ||||
| RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedVideoPayloadType( | ||||
|     const std::string &remote_sdp) { | ||||
|   if (!video_pt_.empty()) { | ||||
|     return RtpPacket::PAYLOAD_TYPE::H264; | ||||
|   } | ||||
|  | ||||
| bool IceTransmission::NegotiateVideoPayloadType(const std::string &remote_sdp) { | ||||
|   std::string remote_video_capabilities; | ||||
|   std::string remote_prefered_video_pt; | ||||
|  | ||||
| @@ -544,24 +600,49 @@ RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedVideoPayloadType( | ||||
|   } | ||||
|   LOG_INFO("remote video capabilities [{}]", remote_video_capabilities.c_str()); | ||||
|  | ||||
|   std::size_t prefered_pt_end = remote_video_capabilities.find(' '); | ||||
|   std::size_t prefered_pt_start = 0; | ||||
|  | ||||
|   while (prefered_pt_start <= remote_video_capabilities.length()) { | ||||
|     std::size_t prefered_pt_end = | ||||
|         remote_video_capabilities.find(' ', prefered_pt_start); | ||||
|     if (prefered_pt_end != std::string::npos) { | ||||
|       remote_prefered_video_pt = | ||||
|           remote_video_capabilities.substr(0, prefered_pt_end); | ||||
|     } else { | ||||
|       remote_prefered_video_pt = remote_video_capabilities; | ||||
|     } | ||||
|   LOG_INFO("remote prefered video pt [{}]", remote_prefered_video_pt.c_str()); | ||||
|  | ||||
|   return RtpPacket::PAYLOAD_TYPE::H264; | ||||
|     remote_prefered_video_pt_ = | ||||
|         (RtpPacket::PAYLOAD_TYPE)(atoi(remote_prefered_video_pt.c_str())); | ||||
|  | ||||
|     bool is_support_this_video_pt = | ||||
|         std::find(support_video_payload_types_.begin(), | ||||
|                   support_video_payload_types_.end(), | ||||
|                   remote_prefered_video_pt_) != | ||||
|         support_video_payload_types_.end(); | ||||
|  | ||||
|     if (is_support_this_video_pt) { | ||||
|       negotiated_video_pt_ = (RtpPacket::PAYLOAD_TYPE)remote_prefered_video_pt_; | ||||
|       break; | ||||
|     } else { | ||||
|       if (prefered_pt_end != std::string::npos) { | ||||
|         prefered_pt_start = prefered_pt_end + 1; | ||||
|       } else { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedAudioPayloadType( | ||||
|     const std::string &remote_sdp) { | ||||
|   if (!audio_pt_.empty()) { | ||||
|     return RtpPacket::PAYLOAD_TYPE::H264; | ||||
|   if (negotiated_video_pt_ == RtpPacket::PAYLOAD_TYPE::UNDEFINED) { | ||||
|     LOG_ERROR("Negotiate video pt failed"); | ||||
|     return false; | ||||
|   } else { | ||||
|     LOG_INFO("negotiated video pt [{}]", (int)negotiated_video_pt_); | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool IceTransmission::NegotiateAudioPayloadType(const std::string &remote_sdp) { | ||||
|   std::string remote_audio_capabilities; | ||||
|   std::string remote_prefered_audio_pt; | ||||
|  | ||||
| @@ -579,23 +660,52 @@ RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedAudioPayloadType( | ||||
|   } | ||||
|   LOG_INFO("remote audio capabilities [{}]", remote_audio_capabilities.c_str()); | ||||
|  | ||||
|   std::size_t prefered_pt_end = remote_audio_capabilities.find(' '); | ||||
|   std::size_t prefered_pt_start = 0; | ||||
|  | ||||
|   while (prefered_pt_start <= remote_audio_capabilities.length()) { | ||||
|     std::size_t prefered_pt_end = | ||||
|         remote_audio_capabilities.find(' ', prefered_pt_start); | ||||
|     if (prefered_pt_end != std::string::npos) { | ||||
|       remote_prefered_audio_pt = | ||||
|           remote_audio_capabilities.substr(0, prefered_pt_end); | ||||
|     } else { | ||||
|       remote_prefered_audio_pt = remote_audio_capabilities; | ||||
|     } | ||||
|   LOG_INFO("remote prefered audio pt [{}]", remote_prefered_audio_pt.c_str()); | ||||
|  | ||||
|   return RtpPacket::PAYLOAD_TYPE::OPUS; | ||||
|     remote_prefered_audio_pt_ = | ||||
|         (RtpPacket::PAYLOAD_TYPE)(atoi(remote_prefered_audio_pt.c_str())); | ||||
|  | ||||
|     bool is_support_this_audio_pt = | ||||
|         std::find(support_audio_payload_types_.begin(), | ||||
|                   support_audio_payload_types_.end(), | ||||
|                   remote_prefered_audio_pt_) != | ||||
|         support_audio_payload_types_.end(); | ||||
|  | ||||
|     if (is_support_this_audio_pt) { | ||||
|       negotiated_audio_pt_ = (RtpPacket::PAYLOAD_TYPE)remote_prefered_audio_pt_; | ||||
|       break; | ||||
|     } else { | ||||
|       if (prefered_pt_end != std::string::npos) { | ||||
|         prefered_pt_start = prefered_pt_end + 1; | ||||
|       } else { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedDataPayloadType( | ||||
|     const std::string &remote_sdp) { | ||||
|   if (!data_pt_.empty()) { | ||||
|     return RtpPacket::PAYLOAD_TYPE::H264; | ||||
|   if (negotiated_audio_pt_ == RtpPacket::PAYLOAD_TYPE::UNDEFINED) { | ||||
|     LOG_ERROR("Negotiate audio pt failed"); | ||||
|     return false; | ||||
|   } else { | ||||
|     LOG_INFO("negotiated audio pt [{}]", (int)negotiated_audio_pt_); | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool IceTransmission::NegotiateDataPayloadType(const std::string &remote_sdp) { | ||||
|   std::string remote_data_capabilities; | ||||
|   std::string remote_prefered_data_pt; | ||||
|  | ||||
|   std::size_t start = | ||||
|       remote_sdp.find("m=data") + std::string("m=data").length(); | ||||
|   if (start != std::string::npos) { | ||||
| @@ -605,11 +715,51 @@ RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedDataPayloadType( | ||||
|     std::string::size_type pos3 = remote_sdp.find(' ', pos2 + 1); | ||||
|     if (end != std::string::npos && pos1 != std::string::npos && | ||||
|         pos2 != std::string::npos && pos3 != std::string::npos) { | ||||
|       data_pt_ = remote_sdp.substr(pos3 + 1, end - pos3 - 1); | ||||
|       remote_data_capabilities = remote_sdp.substr(pos3 + 1, end - pos3 - 1); | ||||
|     } | ||||
|   } | ||||
|   LOG_INFO("data pt [{}]", data_pt_.c_str()); | ||||
|   return RtpPacket::PAYLOAD_TYPE::DATA; | ||||
|   LOG_INFO("remote data capabilities [{}]", remote_data_capabilities.c_str()); | ||||
|  | ||||
|   std::size_t prefered_pt_start = 0; | ||||
|  | ||||
|   while (prefered_pt_start <= remote_data_capabilities.length()) { | ||||
|     std::size_t prefered_pt_end = | ||||
|         remote_data_capabilities.find(' ', prefered_pt_start); | ||||
|     if (prefered_pt_end != std::string::npos) { | ||||
|       remote_prefered_data_pt = | ||||
|           remote_data_capabilities.substr(0, prefered_pt_end); | ||||
|     } else { | ||||
|       remote_prefered_data_pt = remote_data_capabilities; | ||||
|     } | ||||
|  | ||||
|     remote_prefered_data_pt_ = | ||||
|         (RtpPacket::PAYLOAD_TYPE)(atoi(remote_prefered_data_pt.c_str())); | ||||
|  | ||||
|     bool is_support_this_data_pt = | ||||
|         std::find(support_data_payload_types_.begin(), | ||||
|                   support_data_payload_types_.end(), | ||||
|                   remote_prefered_data_pt_) != | ||||
|         support_data_payload_types_.end(); | ||||
|  | ||||
|     if (is_support_this_data_pt) { | ||||
|       negotiated_data_pt_ = (RtpPacket::PAYLOAD_TYPE)remote_prefered_data_pt_; | ||||
|       break; | ||||
|     } else { | ||||
|       if (prefered_pt_end != std::string::npos) { | ||||
|         prefered_pt_start = prefered_pt_end + 1; | ||||
|       } else { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (negotiated_data_pt_ == RtpPacket::PAYLOAD_TYPE::UNDEFINED) { | ||||
|     LOG_ERROR("Negotiate data pt failed"); | ||||
|     return false; | ||||
|   } else { | ||||
|     LOG_INFO("negotiated data pt [{}]", (int)negotiated_data_pt_); | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| int IceTransmission::SendData(DATA_TYPE type, const char *data, size_t size) { | ||||
|   | ||||
| @@ -104,15 +104,13 @@ class IceTransmission { | ||||
|   int SendAnswer(); | ||||
|  | ||||
|  private: | ||||
|   int AppendLocalCapabilities(std::string &remote_sdp); | ||||
|   int AppendLocalCapabilitiesToOffer(const std::string &remote_sdp); | ||||
|   int AppendLocalCapabilitiesToAnswer(const std::string &remote_sdp); | ||||
|   std::string GetRemoteCapabilities(const std::string &remote_sdp); | ||||
|  | ||||
|   RtpPacket::PAYLOAD_TYPE GetAceptedVideoPayloadType( | ||||
|       const std::string &remote_sdp); | ||||
|   RtpPacket::PAYLOAD_TYPE GetAceptedAudioPayloadType( | ||||
|       const std::string &remote_sdp); | ||||
|   RtpPacket::PAYLOAD_TYPE GetAceptedDataPayloadType( | ||||
|       const std::string &remote_sdp); | ||||
|   bool NegotiateVideoPayloadType(const std::string &remote_sdp); | ||||
|   bool NegotiateAudioPayloadType(const std::string &remote_sdp); | ||||
|   bool NegotiateDataPayloadType(const std::string &remote_sdp); | ||||
|  | ||||
|  private: | ||||
|   uint8_t CheckIsRtcpPacket(const char *buffer, size_t size); | ||||
| @@ -125,8 +123,9 @@ class IceTransmission { | ||||
|   bool enable_turn_ = false; | ||||
|   bool use_reliable_ice_ = false; | ||||
|   bool force_turn_ = false; | ||||
|   std::vector<int> video_payload_types_; | ||||
|   std::vector<int> audio_payload_types_; | ||||
|   std::vector<int> support_video_payload_types_; | ||||
|   std::vector<int> support_audio_payload_types_; | ||||
|   std::vector<int> support_data_payload_types_; | ||||
|  | ||||
|   std::string local_sdp_; | ||||
|   std::string remote_sdp_; | ||||
| @@ -176,12 +175,20 @@ class IceTransmission { | ||||
|   std::unique_ptr<IOStatistics> ice_io_statistics_ = nullptr; | ||||
|  | ||||
|  private: | ||||
|   std::string video_pt_; | ||||
|   std::string audio_pt_; | ||||
|   std::string data_pt_; | ||||
|  | ||||
|   RtpPacket::PAYLOAD_TYPE video_codec_payload_type_; | ||||
|   bool remote_capabilities_got_ = false; | ||||
|   RtpPacket::PAYLOAD_TYPE remote_prefered_video_pt_ = | ||||
|       RtpPacket::PAYLOAD_TYPE::UNDEFINED; | ||||
|   RtpPacket::PAYLOAD_TYPE remote_prefered_audio_pt_ = | ||||
|       RtpPacket::PAYLOAD_TYPE::UNDEFINED; | ||||
|   RtpPacket::PAYLOAD_TYPE remote_prefered_data_pt_ = | ||||
|       RtpPacket::PAYLOAD_TYPE::UNDEFINED; | ||||
|   RtpPacket::PAYLOAD_TYPE negotiated_video_pt_ = | ||||
|       RtpPacket::PAYLOAD_TYPE::UNDEFINED; | ||||
|   RtpPacket::PAYLOAD_TYPE negotiated_audio_pt_ = | ||||
|       RtpPacket::PAYLOAD_TYPE::UNDEFINED; | ||||
|   RtpPacket::PAYLOAD_TYPE negotiated_data_pt_ = | ||||
|       RtpPacket::PAYLOAD_TYPE::UNDEFINED; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user