This commit is contained in:
Théo Monnom
2022-05-23 19:36:13 +02:00
parent 8d20e35f02
commit 112bc2de9c
9 changed files with 206 additions and 30 deletions
+24 -3
View File
@@ -1,7 +1,16 @@
# TODO
# This file clearly need rework
# Build system to make it works on every platform
# Also mb automatically download prebuild libwebrtc binary so the users can directly start coding..
cmake_minimum_required(VERSION 3.22)
project(livekit-native)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-DWEBRTC_POSIX=1 -DWEBRTC_MAC=1 -DGLIBCXX_USE_CXX11_ABI=0)
find_package(Boost COMPONENTS system REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
@@ -13,7 +22,19 @@ find_package(spdlog CONFIG REQUIRED)
include_directories(thirdparty/webrtc/include)
file(GLOB_RECURSE SRC src/*)
add_executable(livekit-native ${SRC} main.cpp)
target_link_libraries(livekit-native PRIVATE ${Boost_LIBRARIES} ${Protobuf_LIBRARIES} spdlog::spdlog)
# for cocoa
find_library(CORE_FOUNDATION Foundation)
find_library(APPLICATION_SERVICES ApplicationServices)
find_library(CORE_SERVICES CoreServices)
target_link_libraries(livekit-native PRIVATE
spdlog::spdlog
${Boost_LIBRARIES}
${Protobuf_LIBRARIES}
${CORE_FOUNDATION} ${APPLICATION_SERVICES} ${CORE_SERVICES}
${CMAKE_CURRENT_LIST_DIR}/thirdparty/webrtc/lib/libboringssl.a
${CMAKE_CURRENT_LIST_DIR}/thirdparty/webrtc/lib/libwebrtc.a
)
+10
View File
@@ -0,0 +1,10 @@
//
// Created by Théo Monnom on 21/05/2022.
//
#include "peer_observer.h"
namespace livekit {
} // livekit
+52
View File
@@ -0,0 +1,52 @@
//
// Created by Théo Monnom on 21/05/2022.
//
#ifndef LIVEKIT_NATIVE_PEER_OBSERVER_H
#define LIVEKIT_NATIVE_PEER_OBSERVER_H
#include <api/create_peerconnection_factory.h>
namespace livekit {
class PeerObserver : public webrtc::PeerConnectionObserver {
public:
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override {
};
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {
};
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {
};
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override {
};
void OnRenegotiationNeeded() override {
};
void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override {
};
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override {
};
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override {
};
};
} // livekit
#endif //LIVEKIT_NATIVE_PEER_OBSERVER_H
+1 -11
View File
@@ -9,19 +9,9 @@
#include "signal_client.h"
namespace livekit{
/*class Room {
Room();
~Room();
void Connect(const std::string &url, const std::string &token);
private:
SignalClient m_Client;
};*/
}
} // livekit
#endif //LIVEKIT_NATIVE_ROOM_H
+72 -2
View File
@@ -3,12 +3,82 @@
//
#include "rtc_engine.h"
#include <rtc_base/ssl_adapter.h>
#include <spdlog/spdlog.h>
namespace livekit{
void RTCEngine::configure() {
RTCEngine::RTCEngine() {
}
void RTCEngine::Join(const std::string &url, const std::string &token){
client_.Connect(url, token);
}
void RTCEngine::Update(){
client_.update();
// Fetch SignalResponse ( The whole protocol is async )
auto res = client_.poll();
if(res.has_join())
OnJoin(res.join());
}
void RTCEngine::OnJoin(const JoinResponse &res){
rtc::InitializeSSL();
for(auto& is : res.ice_servers()){
webrtc::PeerConnectionInterface::IceServer ice_server;
for(auto& url : is.urls())
ice_server.urls.push_back(url);
ice_server.username = is.username();
ice_server.password = is.credential();
configuration_.servers.push_back(ice_server);
}
network_thread_ = rtc::Thread::CreateWithSocketServer();
network_thread_->Start();
worker_thread_ = rtc::Thread::Create();
worker_thread_->Start();
signaling_thread_ = rtc::Thread::Create();
signaling_thread_->Start();
webrtc::PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = network_thread_.get();
dependencies.worker_thread = worker_thread_.get();
dependencies.signaling_thread = signaling_thread_.get();
peer_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
if (peer_factory_.get() == nullptr) {
// TODO Make error callback
spdlog::error("Error on CreateModularPeerConnectionFactory");
return;
}
subscriber_ = std::make_unique<PeerTransport>(*this);
publisher_ = std::make_unique<PeerTransport>(*this);
}
}
void RTCEngine::Configure() {
}
RTCEngine::PeerTransport::PeerTransport(const RTCEngine &rtc_engine) {
observer = std::make_unique<PeerObserver>();
webrtc::PeerConnectionDependencies peer_configuration{observer.get()};
webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::PeerConnectionInterface>> opt_peer = rtc_engine.peer_factory_->CreatePeerConnectionOrError(
rtc_engine.configuration_, std::move(peer_configuration));
if (!opt_peer.ok()) {
throw std::runtime_error{"Failed to create a peer connection"};
}
peer_connection = opt_peer.value();
}
} // livekit
+29 -5
View File
@@ -6,20 +6,44 @@
#define LIVEKIT_NATIVE_RTC_ENGINE_H
#include "signal_client.h"
#include "peer_observer.h"
#include <api/peer_connection_interface.h>
namespace livekit{
class RTCEngine {
public:
RTCEngine();
void Join(const std::string &url, const std::string &token);
void Update();
private:
void configure();
void Configure();
void OnJoin(const JoinResponse &res);
private:
SignalClient m_Client;
// Wrapper for our PeerConnection ( Int. Impl. )
class PeerTransport {
public:
explicit PeerTransport(const RTCEngine &rtc_engine);
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
std::unique_ptr<PeerObserver> observer;
};
SignalClient client_;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
webrtc::PeerConnectionInterface::RTCConfiguration configuration_;
std::unique_ptr<rtc::Thread> network_thread_;
std::unique_ptr<rtc::Thread> worker_thread_;
std::unique_ptr<rtc::Thread> signaling_thread_;
std::unique_ptr<PeerTransport> publisher_;
std::unique_ptr<PeerTransport> subscriber_;
};
};
} // livekit
#endif //LIVEKIT_NATIVE_RTC_ENGINE_H
+12 -4
View File
@@ -23,10 +23,10 @@ namespace livekit {
m_URL = ParseURL(url);
m_Token = token;
Start(); // We don't need a thread, everything is async ( + easier to maintain )
start(); // We don't need a thread, everything is async ( + easier to maintain )
}
void SignalClient::Update() {
void SignalClient::update() {
beast::error_code ec;
m_IOContext.poll(ec);
@@ -59,7 +59,15 @@ namespace livekit {
}
}
void SignalClient::Start() {
SignalResponse SignalClient::poll(){
auto& r = m_ReadQueue.front();
m_ReadQueue.pop();
return r;
}
void SignalClient::start() {
m_Resolver.async_resolve(m_URL.host, m_URL.port, beast::bind_front_handler(&SignalClient::OnResolve, this));
}
@@ -128,4 +136,4 @@ namespace livekit {
if (ec)
throw std::runtime_error{"SignalClient::OnWrite - " + ec.message()};
}
}
} // livekit
+5 -4
View File
@@ -17,6 +17,7 @@ namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
// If we keep the code singled threaded here, it'll be easily used in wasm ( Need ws bindings ), tho not sure
namespace livekit {
class SignalClient {
@@ -26,12 +27,12 @@ namespace livekit {
void Connect(const std::string &url, const std::string &token);
void Disconnect();
void Update();
void update();
void Send(SignalRequest req);
SignalResponse Poll();
SignalResponse poll();
private:
void Start();
void start();
// beast handlers
void OnResolve(beast::error_code ec, tcp::resolver::results_type results);
@@ -59,6 +60,6 @@ namespace livekit {
tcp::resolver m_Resolver{m_IOContext};
websocket::stream <beast::tcp_stream> m_WebSocket{m_IOContext};
};
}
} // livekit
#endif //LIVEKIT_NATIVE_SIGNAL_CLIENT_H
+1 -1
View File
@@ -31,6 +31,6 @@ namespace livekit {
throw std::runtime_error{"failed to parse url"};
}
}
} // livekit
#endif //LIVEKIT_NATIVE_UTILS_H