diff --git a/src/ice/ice_agent.cpp b/src/ice/ice_agent.cpp index 296a154..73496ec 100644 --- a/src/ice/ice_agent.cpp +++ b/src/ice/ice_agent.cpp @@ -89,7 +89,9 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed, LOG_ERROR("Failed to add stream"); } - nice_agent_set_stream_name(agent_, stream_id_, "video"); + if (has_video_stream_) { + nice_agent_set_stream_name(agent_, stream_id_, "video"); + } if (enable_turn_) { nice_agent_set_relay_info(agent_, stream_id_, n_components_, @@ -147,11 +149,6 @@ int IceAgent::DestroyIceAgent() { return 0; } -const char *IceAgent::GetLocalStreamSdp() { - local_sdp_ = nice_agent_generate_local_stream_sdp(agent_, stream_id_, true); - return local_sdp_.c_str(); -} - const char *IceAgent::GenerateLocalSdp() { if (!nice_inited_) { LOG_ERROR("Nice agent has not been initialized"); @@ -168,12 +165,60 @@ const char *IceAgent::GenerateLocalSdp() { return nullptr; } - local_sdp_ = nice_agent_generate_local_sdp(agent_); + video_stream_sdp_ = nice_agent_generate_local_sdp(agent_); + audio_stream_sdp_ = video_stream_sdp_; + data_stream_sdp_ = video_stream_sdp_; + local_sdp_ = video_stream_sdp_; + + if (has_audio_stream_) { + std::string to_replace = "video"; + std::string replacement = "audio"; + size_t pos = 0; + while ((pos = audio_stream_sdp_.find(to_replace, pos)) != + std::string::npos) { + audio_stream_sdp_.replace(pos, to_replace.length(), replacement); + pos += replacement.length(); + } + local_sdp_ += audio_stream_sdp_; + } + + if (has_data_stream_) { + std::string to_replace = "video"; + std::string replacement = "data"; + size_t pos = 0; + while ((pos = data_stream_sdp_.find(to_replace, pos)) != + std::string::npos) { + data_stream_sdp_.replace(pos, to_replace.length(), replacement); + pos += replacement.length(); + } + local_sdp_ += data_stream_sdp_; + } + LOG_INFO("Generate local sdp:[\n{}]", local_sdp_.c_str()); return local_sdp_.c_str(); } +const char *IceAgent::GetLocalStreamSdp(uint32_t stream_id) { + if (!nice_inited_) { + LOG_ERROR("Nice agent has not been initialized"); + return nullptr; + } + + if (nullptr == agent_) { + LOG_ERROR("Nice agent is nullptr"); + return nullptr; + } + + if (destroyed_) { + LOG_ERROR("Nice agent is destroyed"); + return nullptr; + } + + local_sdp_ = nice_agent_generate_local_stream_sdp(agent_, stream_id, true); + return local_sdp_.c_str(); +} + int IceAgent::SetRemoteSdp(const char *remote_sdp) { if (!nice_inited_) { LOG_ERROR("Nice agent has not been initialized"); diff --git a/src/ice/ice_agent.h b/src/ice/ice_agent.h index 20cf5ac..2531057 100644 --- a/src/ice/ice_agent.h +++ b/src/ice/ice_agent.h @@ -43,10 +43,10 @@ class IceAgent { int DestroyIceAgent(); - const char* GetLocalStreamSdp(); - const char* GenerateLocalSdp(); + const char* GetLocalStreamSdp(uint32_t stream_id); + int SetRemoteSdp(const char* remote_sdp); int GatherCandidates(); @@ -70,6 +70,17 @@ class IceAgent { std::string turn_username_ = ""; std::string turn_password_ = ""; + bool has_video_stream_ = true; + uint32_t n_video_streams_ = 1; + std::string video_stream_sdp_; + bool has_audio_stream_ = true; + uint32_t n_audio_streams_ = 1; + std::string audio_stream_sdp_; + bool has_data_stream_ = true; + uint32_t n_data_streams_ = 1; + std::string data_stream_sdp_; + + public: std::thread nice_thread_; std::atomic agent_{nullptr}; std::atomic gloop_{nullptr}; diff --git a/src/transmission/ice_transmission.cpp b/src/transmission/ice_transmission.cpp index 2b4ca1f..1e8f9d2 100644 --- a/src/transmission/ice_transmission.cpp +++ b/src/transmission/ice_transmission.cpp @@ -380,35 +380,30 @@ int IceTransmission::GatherCandidates() { } int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) { - ice_agent_->SetRemoteSdp(remote_sdp.c_str()); - // LOG_INFO("[{}] set remote sdp", user_id_); - // GetAceptedVideoPayloadType(remote_sdp); // GetAceptedAudioPayloadType(remote_sdp); - remote_ice_username_ = GetIceUsername(remote_sdp); + std::string media_stream_sdp = GetLocalCapabilitiesToSdp(remote_sdp); + LOG_ERROR("media_stream_sdp: [{}] [{}]", media_stream_sdp, remote_sdp); + + ice_agent_->SetRemoteSdp(media_stream_sdp.c_str()); + // LOG_INFO("[{}] set remote sdp", user_id_); + + remote_ice_username_ = GetIceUsername(media_stream_sdp); return 0; } int IceTransmission::SendOffer() { - local_sdp_ = use_trickle_ice_ ? ice_agent_->GetLocalStreamSdp() - : ice_agent_->GenerateLocalSdp(); + local_sdp_ = ice_agent_->GenerateLocalSdp(); - std::string toReplace = "ICE/SDP"; - std::string replacement = "UDP/TLS/RTP/SAVPF 111 114 115 116 123 124 125"; - - size_t pos = 0; - while ((pos = local_sdp_.find(toReplace, pos)) != std::string::npos) { - local_sdp_.replace(pos, toReplace.length(), replacement); - pos += replacement.length(); - } + AppendLocalCapabilitiesToSdp(local_sdp_); json message = {{"type", "offer"}, {"transmission_id", transmission_id_}, {"user_id", user_id_}, {"remote_user_id", remote_user_id_}, {"sdp", local_sdp_.c_str()}}; - LOG_INFO("Send offer with sdp:\n[\n{}]", local_sdp_.c_str()); + // LOG_INFO("Send offer with sdp:\n[\n{}]", local_sdp_.c_str()); if (ice_ws_transport_) { ice_ws_transport_->Send(message.dump()); LOG_INFO("[{}->{}] send offer", user_id_, remote_user_id_); @@ -417,14 +412,13 @@ int IceTransmission::SendOffer() { } int IceTransmission::SendAnswer() { - local_sdp_ = use_trickle_ice_ ? ice_agent_->GetLocalStreamSdp() - : ice_agent_->GenerateLocalSdp(); + local_sdp_ = ice_agent_->GenerateLocalSdp(); json message = {{"type", "answer"}, {"transmission_id", transmission_id_}, {"user_id", user_id_}, {"remote_user_id", remote_user_id_}, {"sdp", local_sdp_.c_str()}}; - LOG_INFO("Send answer with sdp:\n[\n{}]", local_sdp_.c_str()); + // LOG_INFO("Send answer with sdp:\n[\n{}]", local_sdp_.c_str()); if (ice_ws_transport_) { ice_ws_transport_->Send(message.dump()); LOG_INFO("[{}->{}] send answer", user_id_, remote_user_id_); @@ -433,18 +427,78 @@ int IceTransmission::SendAnswer() { return 0; } -// int IceTransmission::AppendLocalCapabilitiesToSdp() { -// std::string toReplace = "ICE/SDP"; -// std::string replacement = "UDP/TLS/RTP/SAVPF 111 114 115 116 123 124 125"; +int IceTransmission::AppendLocalCapabilitiesToSdp(std::string &remote_sdp) { + std::string to_replace = "ICE/SDP"; + std::string video_capabilities = "UDP/TLS/RTP/SAVPF 96 97 98 99"; + std::string audio_capabilities = "UDP/TLS/RTP/SAVPF 111"; + std::string data_capabilities = "UDP/TLS/RTP/SAVPF 127"; -// size_t pos = 0; -// while ((pos = local_sdp_.find(toReplace, pos)) != std::string::npos) { -// local_sdp_.replace(pos, toReplace.length(), replacement); -// pos += replacement.length(); -// } + std::size_t video_start = remote_sdp.find("m=video"); + std::size_t video_end = remote_sdp.find("\n", video_start); + std::size_t audio_start = remote_sdp.find("m=audio"); + std::size_t audio_end = remote_sdp.find("\n", audio_start); + std::size_t data_start = remote_sdp.find("m=data"); + std::size_t data_end = remote_sdp.find("\n", data_start); -// return 0; -// } + 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(), video_capabilities); + pos += video_capabilities.length(); + } + } + + 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(), audio_capabilities); + pos += audio_capabilities.length(); + } + } + + 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(), data_capabilities); + pos += data_capabilities.length(); + } + } + + return 0; +} + +std::string IceTransmission::GetLocalCapabilitiesToSdp( + const std::string &remote_sdp) { + std::string media_stream_sdp; + std::size_t video_start = remote_sdp.find("m=video"); + std::size_t video_end = remote_sdp.find("m=audio"); + std::size_t audio_start = video_end; + std::size_t audio_end = remote_sdp.find("m=data"); + std::size_t data_start = audio_end; + std::size_t data_end = remote_sdp.find("a=candidate"); + std::size_t candidate_start = data_end; + + if ((video_start != std::string::npos && video_end != std::string::npos) || + (audio_start != std::string::npos && audio_end != std::string::npos) || + (data_start != std::string::npos && data_end != std::string::npos)) { + if (video_start != std::string::npos && video_end != std::string::npos) { + media_stream_sdp = + remote_sdp.substr(video_start, video_end - video_start); + } else if (audio_start != std::string::npos && + audio_end != std::string::npos) { + media_stream_sdp = + remote_sdp.substr(audio_start, audio_end - audio_start); + } else { + media_stream_sdp = remote_sdp.substr(data_start, data_end - data_start); + } + + if (candidate_start != std::string::npos) { + media_stream_sdp += remote_sdp.substr(candidate_start); + } + } else { + return remote_sdp; + } + + return media_stream_sdp; +} RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedVideoPayloadType( const std::string &remote_sdp) { diff --git a/src/transmission/ice_transmission.h b/src/transmission/ice_transmission.h index 9da6156..e3f7fbf 100644 --- a/src/transmission/ice_transmission.h +++ b/src/transmission/ice_transmission.h @@ -104,6 +104,9 @@ class IceTransmission { int SendAnswer(); private: + int AppendLocalCapabilitiesToSdp(std::string &remote_sdp); + std::string GetLocalCapabilitiesToSdp(const std::string &remote_sdp); + RtpPacket::PAYLOAD_TYPE GetAceptedVideoPayloadType( const std::string &remote_sdp); RtpPacket::PAYLOAD_TYPE GetAceptedAudioPayloadType(