mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-27 04:35:34 +08:00
Add libnice as ice agent
This commit is contained in:
@@ -69,6 +69,8 @@ int IceAgent::CreateIceAgent(juice_cb_state_changed_t on_state_changed,
|
||||
|
||||
agent_ = juice_create(&config_);
|
||||
|
||||
LOG_INFO("Juice agent init finish");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "juice/juice.h"
|
||||
#include "nice/agent.h"
|
||||
|
||||
class IceAgent {
|
||||
public:
|
||||
114
src/ice/libnice/ice_agent.cpp
Normal file
114
src/ice/libnice/ice_agent.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "ice_agent.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
IceAgent::IceAgent(std::string &stun_ip, uint16_t stun_port,
|
||||
std::string &turn_ip, uint16_t turn_port,
|
||||
std::string &turn_username, std::string &turn_password)
|
||||
: stun_ip_(stun_ip),
|
||||
stun_port_(stun_port),
|
||||
turn_ip_(turn_ip),
|
||||
turn_port_(turn_port),
|
||||
turn_username_(turn_username),
|
||||
turn_password_(turn_password) {}
|
||||
|
||||
IceAgent::~IceAgent() {}
|
||||
|
||||
int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
||||
nice_cb_candidate_t on_candidate,
|
||||
nice_cb_gathering_done_t on_gathering_done,
|
||||
nice_cb_recv_t on_recv, void *user_ptr) {
|
||||
g_networking_init();
|
||||
|
||||
gloop_ = g_main_loop_new(NULL, FALSE);
|
||||
// Create the nice agent_
|
||||
agent_ = nice_agent_new(g_main_loop_get_context(gloop_),
|
||||
NICE_COMPATIBILITY_RFC5245);
|
||||
if (agent_ == NULL) {
|
||||
LOG_ERROR("Failed to create agent_");
|
||||
}
|
||||
|
||||
g_object_set(agent_, "stun-server", stun_ip_.c_str(), NULL);
|
||||
g_object_set(agent_, "stun-server-port", stun_port_, NULL);
|
||||
|
||||
g_object_set(agent_, "controlling-mode", controlling_, NULL);
|
||||
|
||||
// Connect to the signals
|
||||
g_signal_connect(agent_, "candidate-gathering-done",
|
||||
G_CALLBACK(on_gathering_done), NULL);
|
||||
g_signal_connect(agent_, "new-selected-pair", G_CALLBACK(on_candidate), NULL);
|
||||
g_signal_connect(agent_, "component-state-changed",
|
||||
G_CALLBACK(on_state_changed), NULL);
|
||||
|
||||
// Create a new stream with one component
|
||||
stream_id_ = nice_agent_add_stream(agent_, 1);
|
||||
if (stream_id_ == 0) {
|
||||
LOG_ERROR("Failed to add stream");
|
||||
}
|
||||
nice_agent_set_stream_name(agent_, stream_id_, "video");
|
||||
|
||||
// Attach to the component to receive the data
|
||||
// Without this call, candidates cannot be gathered
|
||||
nice_agent_attach_recv(agent_, stream_id_, 1, g_main_loop_get_context(gloop_),
|
||||
on_recv, NULL);
|
||||
|
||||
LOG_INFO("Nice agent init finish");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IceAgent::DestoryIceAgent() {
|
||||
g_object_unref(agent_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *IceAgent::GenerateLocalSdp() {
|
||||
if (nullptr == agent_) {
|
||||
LOG_INFO("agent_ is nullptr");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
local_sdp_ = nice_agent_generate_local_sdp(agent_);
|
||||
// LOG_INFO("Generate local sdp:[\n{}]", local_sdp_);
|
||||
|
||||
return local_sdp_;
|
||||
}
|
||||
|
||||
int IceAgent::SetRemoteSdp(const char *remote_sdp) {
|
||||
int ret = nice_agent_parse_remote_sdp(agent_, remote_sdp);
|
||||
if (ret > 0) {
|
||||
return 0;
|
||||
} else {
|
||||
LOG_ERROR("Failed to parse remote data");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int IceAgent::GatherCandidates() {
|
||||
if (!nice_agent_gather_candidates(agent_, stream_id_)) {
|
||||
LOG_ERROR("Failed to start candidate gathering");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NiceComponentState IceAgent::GetIceState() {
|
||||
state_ = nice_agent_get_component_state(agent_, stream_id_, 1);
|
||||
|
||||
return state_;
|
||||
}
|
||||
|
||||
int IceAgent::Send(const char *data, size_t size) {
|
||||
if (NiceComponentState::NICE_COMPONENT_STATE_READY !=
|
||||
nice_agent_get_component_state(agent_, stream_id_, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nice_agent_send(agent_, stream_id_, 1, size, data);
|
||||
return 0;
|
||||
}
|
||||
66
src/ice/libnice/ice_agent.h
Normal file
66
src/ice/libnice/ice_agent.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef _ICE_AGENT_H_
|
||||
#define _ICE_AGENT_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gio/gnetworking.h"
|
||||
#include "nice/agent.h"
|
||||
|
||||
#define NICE_MAX_SDP_STRING_LEN 4096
|
||||
|
||||
typedef void (*nice_cb_state_changed_t)(NiceAgent* agent, guint stream_id,
|
||||
guint component_id,
|
||||
NiceComponentState state,
|
||||
gpointer data);
|
||||
typedef void (*nice_cb_candidate_t)(NiceAgent* agent, guint stream_id,
|
||||
guint component_id, const char* sdp,
|
||||
gpointer data);
|
||||
typedef void (*nice_cb_gathering_done_t)(NiceAgent* agent, guint stream_id,
|
||||
gpointer data);
|
||||
typedef void (*nice_cb_recv_t)(NiceAgent* agent, guint stream_id,
|
||||
guint component_id, guint size, gchar* buffer,
|
||||
gpointer data);
|
||||
|
||||
class IceAgent {
|
||||
public:
|
||||
IceAgent(std::string& stun_ip, uint16_t stun_port, std::string& turn_ip,
|
||||
uint16_t turn_port, std::string& turn_username,
|
||||
std::string& turn_password);
|
||||
~IceAgent();
|
||||
|
||||
int CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
||||
nice_cb_candidate_t on_candidate,
|
||||
nice_cb_gathering_done_t on_gathering_done,
|
||||
nice_cb_recv_t on_recv, void* user_ptr);
|
||||
|
||||
int DestoryIceAgent();
|
||||
|
||||
char* GenerateLocalSdp();
|
||||
|
||||
int SetRemoteSdp(const char* remote_sdp);
|
||||
|
||||
int GatherCandidates();
|
||||
|
||||
NiceComponentState GetIceState();
|
||||
|
||||
int SetRemoteGatheringDone();
|
||||
|
||||
int Send(const char* data, size_t size);
|
||||
|
||||
private:
|
||||
std::string stun_ip_ = "";
|
||||
uint16_t stun_port_ = 0;
|
||||
std::string turn_ip_ = "";
|
||||
uint16_t turn_port_ = 0;
|
||||
std::string turn_username_ = "";
|
||||
std::string turn_password_ = "";
|
||||
NiceAgent* agent_ = nullptr;
|
||||
GMainLoop* gloop_;
|
||||
bool controlling_ = false;
|
||||
uint32_t stream_id_ = 0;
|
||||
// char local_sdp_[NICE_MAX_SDP_STRING_LEN];
|
||||
char* local_sdp_ = nullptr;
|
||||
NiceComponentState state_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -114,6 +114,63 @@ int IceTransmission::InitIceTransmission(std::string &stun_ip, int stun_port,
|
||||
ice_agent_ = std::make_unique<IceAgent>(
|
||||
stun_ip, stun_port, turn_ip, turn_port, turn_username, turn_password);
|
||||
|
||||
#ifdef USE_NICE
|
||||
ice_agent_->CreateIceAgent(
|
||||
[](NiceAgent *agent, guint stream_id, guint component_id,
|
||||
NiceComponentState state, gpointer user_ptr) {
|
||||
if (user_ptr) {
|
||||
IceTransmission *ice_transmission_obj =
|
||||
static_cast<IceTransmission *>(user_ptr);
|
||||
LOG_INFO("[{}->{}] state_change: {}", ice_transmission_obj->user_id_,
|
||||
ice_transmission_obj->remote_user_id_,
|
||||
nice_component_state_to_string(state));
|
||||
ice_transmission_obj->state_ = state;
|
||||
ice_transmission_obj->on_ice_status_change_(
|
||||
nice_component_state_to_string(state));
|
||||
} else {
|
||||
LOG_INFO("state_change: {}", nice_component_state_to_string(state));
|
||||
}
|
||||
},
|
||||
[](NiceAgent *agent, guint stream_id, guint component_id, const char *sdp,
|
||||
gpointer user_ptr) { LOG_INFO("candadite: {}", sdp); },
|
||||
[](NiceAgent *agent, guint stream_id, gpointer user_ptr) {
|
||||
// non-trickle
|
||||
if (user_ptr) {
|
||||
IceTransmission *ice_transmission_obj =
|
||||
static_cast<IceTransmission *>(user_ptr);
|
||||
LOG_INFO("[{}] gather_done", ice_transmission_obj->user_id_);
|
||||
|
||||
if (ice_transmission_obj->offer_peer_) {
|
||||
ice_transmission_obj->GetLocalSdp();
|
||||
ice_transmission_obj->SendOffer();
|
||||
|
||||
} else {
|
||||
ice_transmission_obj->CreateAnswer();
|
||||
ice_transmission_obj->SendAnswer();
|
||||
}
|
||||
}
|
||||
},
|
||||
[](NiceAgent *agent, guint stream_id, guint component_id, guint size,
|
||||
gchar *buffer, gpointer user_ptr) {
|
||||
if (user_ptr) {
|
||||
IceTransmission *ice_transmission_obj =
|
||||
static_cast<IceTransmission *>(user_ptr);
|
||||
if (ice_transmission_obj) {
|
||||
if (ice_transmission_obj->CheckIsVideoPacket(buffer, size)) {
|
||||
RtpPacket packet((uint8_t *)buffer, size);
|
||||
ice_transmission_obj->rtp_video_receiver_->InsertRtpPacket(
|
||||
packet);
|
||||
} else if (ice_transmission_obj->CheckIsDataPacket(buffer, size)) {
|
||||
RtpPacket packet((uint8_t *)buffer, size);
|
||||
ice_transmission_obj->rtp_data_receiver_->InsertRtpPacket(packet);
|
||||
} else if (ice_transmission_obj->CheckIsRtcpPacket(buffer, size)) {
|
||||
// LOG_ERROR("Rtcp packet [{}]", (uint8_t)(buffer[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
this);
|
||||
#else
|
||||
ice_agent_->CreateIceAgent(
|
||||
[](juice_agent_t *agent, juice_state_t state, void *user_ptr) {
|
||||
if (user_ptr) {
|
||||
@@ -172,6 +229,7 @@ int IceTransmission::InitIceTransmission(std::string &stun_ip, int stun_port,
|
||||
}
|
||||
},
|
||||
this);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -216,11 +274,6 @@ int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IceTransmission::AddRemoteCandidate(const std::string &remote_candidate) {
|
||||
ice_agent_->AddRemoteCandidates(remote_candidate.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IceTransmission::CreateOffer() {
|
||||
LOG_INFO("[{}] create offer", user_id_);
|
||||
GatherCandidates();
|
||||
@@ -262,7 +315,11 @@ int IceTransmission::SendAnswer() {
|
||||
}
|
||||
|
||||
int IceTransmission::SendData(DATA_TYPE type, const char *data, size_t size) {
|
||||
if (JUICE_STATE_COMPLETED == state_) {
|
||||
#ifdef USE_NICE
|
||||
if (NiceComponentState::NICE_COMPONENT_STATE_READY == state_) {
|
||||
#else
|
||||
if (juice_state_t::JUICE_STATE_COMPLETED == state_) {
|
||||
#endif
|
||||
std::vector<RtpPacket> packets;
|
||||
|
||||
if (DATA_TYPE::VIDEO == type) {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "congestion_control.h"
|
||||
#include "ice_agent.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "rtp_codec.h"
|
||||
#include "rtp_data_receiver.h"
|
||||
@@ -14,6 +13,14 @@
|
||||
#include "rtp_video_sender.h"
|
||||
#include "ws_transmission.h"
|
||||
|
||||
#define USE_NICE 1
|
||||
|
||||
#ifdef USE_NICE
|
||||
#include "libnice/ice_agent.h"
|
||||
#else
|
||||
#include "libjuice/ice_agent.h"
|
||||
#endif
|
||||
|
||||
class IceTransmission {
|
||||
public:
|
||||
typedef enum { VIDEO = 96, AUDIO = 97, DATA = 127 } DATA_TYPE;
|
||||
@@ -64,8 +71,6 @@ class IceTransmission {
|
||||
|
||||
int SetRemoteSdp(const std::string &remote_sdp);
|
||||
|
||||
int AddRemoteCandidate(const std::string &remote_candidate);
|
||||
|
||||
int CreateOffer();
|
||||
|
||||
int SendOffer();
|
||||
@@ -101,7 +106,11 @@ class IceTransmission {
|
||||
std::string remote_user_id_ = "";
|
||||
bool offer_peer_ = true;
|
||||
std::string remote_ice_username_ = "";
|
||||
#ifdef USE_NICE
|
||||
NiceComponentState state_ = NICE_COMPONENT_STATE_DISCONNECTED;
|
||||
#else
|
||||
juice_state_t state_ = JUICE_STATE_DISCONNECTED;
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::unique_ptr<RtpCodec> video_rtp_codec_ = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user