mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] support multiple streams in sdp
This commit is contained in:
@@ -89,7 +89,9 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
|||||||
LOG_ERROR("Failed to add stream");
|
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_) {
|
if (enable_turn_) {
|
||||||
nice_agent_set_relay_info(agent_, stream_id_, n_components_,
|
nice_agent_set_relay_info(agent_, stream_id_, n_components_,
|
||||||
@@ -147,11 +149,6 @@ int IceAgent::DestroyIceAgent() {
|
|||||||
return 0;
|
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() {
|
const char *IceAgent::GenerateLocalSdp() {
|
||||||
if (!nice_inited_) {
|
if (!nice_inited_) {
|
||||||
LOG_ERROR("Nice agent has not been initialized");
|
LOG_ERROR("Nice agent has not been initialized");
|
||||||
@@ -168,12 +165,60 @@ const char *IceAgent::GenerateLocalSdp() {
|
|||||||
return nullptr;
|
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());
|
LOG_INFO("Generate local sdp:[\n{}]", local_sdp_.c_str());
|
||||||
|
|
||||||
return 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) {
|
int IceAgent::SetRemoteSdp(const char *remote_sdp) {
|
||||||
if (!nice_inited_) {
|
if (!nice_inited_) {
|
||||||
LOG_ERROR("Nice agent has not been initialized");
|
LOG_ERROR("Nice agent has not been initialized");
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ class IceAgent {
|
|||||||
|
|
||||||
int DestroyIceAgent();
|
int DestroyIceAgent();
|
||||||
|
|
||||||
const char* GetLocalStreamSdp();
|
|
||||||
|
|
||||||
const char* GenerateLocalSdp();
|
const char* GenerateLocalSdp();
|
||||||
|
|
||||||
|
const char* GetLocalStreamSdp(uint32_t stream_id);
|
||||||
|
|
||||||
int SetRemoteSdp(const char* remote_sdp);
|
int SetRemoteSdp(const char* remote_sdp);
|
||||||
|
|
||||||
int GatherCandidates();
|
int GatherCandidates();
|
||||||
@@ -70,6 +70,17 @@ class IceAgent {
|
|||||||
std::string turn_username_ = "";
|
std::string turn_username_ = "";
|
||||||
std::string turn_password_ = "";
|
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::thread nice_thread_;
|
||||||
std::atomic<NiceAgent*> agent_{nullptr};
|
std::atomic<NiceAgent*> agent_{nullptr};
|
||||||
std::atomic<GMainLoop*> gloop_{nullptr};
|
std::atomic<GMainLoop*> gloop_{nullptr};
|
||||||
|
|||||||
@@ -380,35 +380,30 @@ int IceTransmission::GatherCandidates() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) {
|
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);
|
// GetAceptedVideoPayloadType(remote_sdp);
|
||||||
// GetAceptedAudioPayloadType(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IceTransmission::SendOffer() {
|
int IceTransmission::SendOffer() {
|
||||||
local_sdp_ = use_trickle_ice_ ? ice_agent_->GetLocalStreamSdp()
|
local_sdp_ = ice_agent_->GenerateLocalSdp();
|
||||||
: ice_agent_->GenerateLocalSdp();
|
|
||||||
|
|
||||||
std::string toReplace = "ICE/SDP";
|
AppendLocalCapabilitiesToSdp(local_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();
|
|
||||||
}
|
|
||||||
|
|
||||||
json message = {{"type", "offer"},
|
json message = {{"type", "offer"},
|
||||||
{"transmission_id", transmission_id_},
|
{"transmission_id", transmission_id_},
|
||||||
{"user_id", user_id_},
|
{"user_id", user_id_},
|
||||||
{"remote_user_id", remote_user_id_},
|
{"remote_user_id", remote_user_id_},
|
||||||
{"sdp", local_sdp_.c_str()}};
|
{"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_) {
|
if (ice_ws_transport_) {
|
||||||
ice_ws_transport_->Send(message.dump());
|
ice_ws_transport_->Send(message.dump());
|
||||||
LOG_INFO("[{}->{}] send offer", user_id_, remote_user_id_);
|
LOG_INFO("[{}->{}] send offer", user_id_, remote_user_id_);
|
||||||
@@ -417,14 +412,13 @@ int IceTransmission::SendOffer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int IceTransmission::SendAnswer() {
|
int IceTransmission::SendAnswer() {
|
||||||
local_sdp_ = use_trickle_ice_ ? ice_agent_->GetLocalStreamSdp()
|
local_sdp_ = ice_agent_->GenerateLocalSdp();
|
||||||
: ice_agent_->GenerateLocalSdp();
|
|
||||||
json message = {{"type", "answer"},
|
json message = {{"type", "answer"},
|
||||||
{"transmission_id", transmission_id_},
|
{"transmission_id", transmission_id_},
|
||||||
{"user_id", user_id_},
|
{"user_id", user_id_},
|
||||||
{"remote_user_id", remote_user_id_},
|
{"remote_user_id", remote_user_id_},
|
||||||
{"sdp", local_sdp_.c_str()}};
|
{"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_) {
|
if (ice_ws_transport_) {
|
||||||
ice_ws_transport_->Send(message.dump());
|
ice_ws_transport_->Send(message.dump());
|
||||||
LOG_INFO("[{}->{}] send answer", user_id_, remote_user_id_);
|
LOG_INFO("[{}->{}] send answer", user_id_, remote_user_id_);
|
||||||
@@ -433,18 +427,78 @@ int IceTransmission::SendAnswer() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int IceTransmission::AppendLocalCapabilitiesToSdp() {
|
int IceTransmission::AppendLocalCapabilitiesToSdp(std::string &remote_sdp) {
|
||||||
// std::string toReplace = "ICE/SDP";
|
std::string to_replace = "ICE/SDP";
|
||||||
// std::string replacement = "UDP/TLS/RTP/SAVPF 111 114 115 116 123 124 125";
|
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;
|
std::size_t video_start = remote_sdp.find("m=video");
|
||||||
// while ((pos = local_sdp_.find(toReplace, pos)) != std::string::npos) {
|
std::size_t video_end = remote_sdp.find("\n", video_start);
|
||||||
// local_sdp_.replace(pos, toReplace.length(), replacement);
|
std::size_t audio_start = remote_sdp.find("m=audio");
|
||||||
// pos += replacement.length();
|
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(
|
RtpPacket::PAYLOAD_TYPE IceTransmission::GetAceptedVideoPayloadType(
|
||||||
const std::string &remote_sdp) {
|
const std::string &remote_sdp) {
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ class IceTransmission {
|
|||||||
int SendAnswer();
|
int SendAnswer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int AppendLocalCapabilitiesToSdp(std::string &remote_sdp);
|
||||||
|
std::string GetLocalCapabilitiesToSdp(const std::string &remote_sdp);
|
||||||
|
|
||||||
RtpPacket::PAYLOAD_TYPE GetAceptedVideoPayloadType(
|
RtpPacket::PAYLOAD_TYPE GetAceptedVideoPayloadType(
|
||||||
const std::string &remote_sdp);
|
const std::string &remote_sdp);
|
||||||
RtpPacket::PAYLOAD_TYPE GetAceptedAudioPayloadType(
|
RtpPacket::PAYLOAD_TYPE GetAceptedAudioPayloadType(
|
||||||
|
|||||||
Reference in New Issue
Block a user