feat: forward libwebrtc logs (#75)

This commit is contained in:
Théo Monnom
2023-05-24 18:37:35 +02:00
committed by GitHub
parent d5b4a8f6fc
commit 3f61e07e09
19 changed files with 300 additions and 98 deletions
+3 -1
View File
@@ -43,7 +43,9 @@ jobs:
- name: Install linux dependencies
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev
run: |
sudo apt update -y
sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev
- uses: actions/checkout@v3
with:
+3 -1
View File
@@ -51,7 +51,9 @@ jobs:
- name: Install linux dependencies
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev
run: |
sudo apt update -y
sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev
- uses: actions/checkout@v3
with:
+3 -1
View File
@@ -37,7 +37,9 @@ jobs:
- name: Install linux dependencies
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev
run: |
sudo apt update -y
sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev
- uses: actions/checkout@v3
with:
Generated
+15 -13
View File
@@ -41,12 +41,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.0"
@@ -263,6 +257,12 @@ dependencies = [
"parking_lot_core",
]
[[package]]
name = "data-encoding"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "digest"
version = "0.10.6"
@@ -735,7 +735,7 @@ version = "8.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378"
dependencies = [
"base64 0.21.0",
"base64",
"ring",
"serde",
"serde_json",
@@ -843,8 +843,10 @@ dependencies = [
"env_logger",
"futures",
"js-sys",
"lazy_static",
"livekit-protocol",
"log",
"parking_lot",
"thiserror",
"tokio",
"wasm-bindgen",
@@ -1234,7 +1236,7 @@ version = "0.11.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
dependencies = [
"base64 0.21.0",
"base64",
"bytes",
"encoding_rs",
"futures-core",
@@ -1614,9 +1616,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
version = "0.18.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c"
dependencies = [
"futures-util",
"log",
@@ -1686,13 +1688,13 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "tungstenite"
version = "0.18.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67"
dependencies = [
"base64 0.13.1",
"byteorder",
"bytes",
"data-encoding",
"http",
"httparse",
"log",
+47 -12
View File
@@ -181,12 +181,6 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.0"
@@ -203,7 +197,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
name = "basic_room"
version = "0.1.0"
dependencies = [
"env_logger",
"livekit",
"log",
"tokio",
]
@@ -604,6 +600,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "data-encoding"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "digest"
version = "0.10.6"
@@ -727,6 +729,19 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "epaint"
version = "0.21.0"
@@ -1209,6 +1224,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.26"
@@ -1314,6 +1335,18 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
[[package]]
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.48.0",
]
[[package]]
name = "itertools"
version = "0.10.5"
@@ -1481,8 +1514,10 @@ dependencies = [
"cxx",
"futures",
"js-sys",
"lazy_static",
"livekit-protocol",
"log",
"parking_lot",
"thiserror",
"tokio",
"wasm-bindgen",
@@ -2305,7 +2340,7 @@ version = "0.11.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
dependencies = [
"base64 0.21.0",
"base64",
"bytes",
"encoding_rs",
"futures-core",
@@ -2851,9 +2886,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
version = "0.18.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c"
dependencies = [
"futures-util",
"log",
@@ -2972,13 +3007,13 @@ checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746"
[[package]]
name = "tungstenite"
version = "0.18.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67"
dependencies = [
"base64 0.13.1",
"byteorder",
"bytes",
"data-encoding",
"http",
"httparse",
"log",
+2
View File
@@ -5,4 +5,6 @@ edition = "2021"
[dependencies]
tokio = { version = "1", features = ["full"] }
env_logger = "0.10"
livekit = { path = "../../livekit", version = "0.1.1" }
log = "0.4"
+6 -3
View File
@@ -1,18 +1,21 @@
use livekit::prelude::*;
use std::env;
// Basic demo to connect to a room using the specified env variables
// Connect to a room using the specified env variables
// and print all incoming events
#[tokio::main]
async fn main() {
env_logger::init();
let url = env::var("LIVEKIT_URL").expect("LIVEKIT_URL is not set");
let token = env::var("LIVEKIT_TOKEN").expect("LIVEKIT_TOKEN is not set");
let (room, mut rx) = Room::connect(&url, &token).await.unwrap();
let session = room.session();
println!("Connected to room: {} - {}", session.name(), session.sid());
log::info!("Connected to room: {} - {}", session.name(), session.sid());
while let Some(msg) = rx.recv().await {
println!("Event: {:?}", msg);
log::info!("Event: {:?}", msg);
}
}
+2
View File
@@ -14,6 +14,8 @@ thiserror = "1.0"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
webrtc-sys = { path = "../webrtc-sys", version = "0.1.1" }
lazy_static = "1.4"
parking_lot = { version = "0.12.1", features = ["send_guard"] }
futures = { version = "0.3" }
tokio = { version = "1", features = ["full"] }
cxx = "1.0"
@@ -11,80 +11,76 @@ use crate::video_source::native::NativeVideoSource;
use crate::MediaType;
use crate::RtcError;
use cxx::SharedPtr;
use std::sync::Arc;
use cxx::UniquePtr;
use lazy_static::lazy_static;
use parking_lot::Mutex;
use std::sync::{Arc, Weak};
use webrtc_sys::logsink as sys_ls;
use webrtc_sys::peer_connection as sys_pc;
use webrtc_sys::peer_connection_factory as sys_pcf;
use webrtc_sys::rtc_error as sys_err;
use webrtc_sys::webrtc as sys_webrtc;
impl From<IceServer> for sys_pcf::ffi::ICEServer {
fn from(value: IceServer) -> Self {
sys_pcf::ffi::ICEServer {
urls: value.urls,
username: value.username,
password: value.password,
}
}
lazy_static! {
static ref RTC_RUNTIME: Mutex<Weak<RtcRuntime>> = Mutex::new(Weak::new());
}
impl From<ContinualGatheringPolicy> for sys_pcf::ffi::ContinualGatheringPolicy {
fn from(value: ContinualGatheringPolicy) -> Self {
match value {
ContinualGatheringPolicy::GatherOnce => {
sys_pcf::ffi::ContinualGatheringPolicy::GatherOnce
}
ContinualGatheringPolicy::GatherContinually => {
sys_pcf::ffi::ContinualGatheringPolicy::GatherContinually
}
}
}
}
impl From<IceTransportsType> for sys_pcf::ffi::IceTransportsType {
fn from(value: IceTransportsType) -> Self {
match value {
IceTransportsType::None => sys_pcf::ffi::IceTransportsType::None,
IceTransportsType::Relay => sys_pcf::ffi::IceTransportsType::Relay,
IceTransportsType::NoHost => sys_pcf::ffi::IceTransportsType::NoHost,
IceTransportsType::All => sys_pcf::ffi::IceTransportsType::All,
}
}
}
impl From<RtcConfiguration> for sys_pcf::ffi::RTCConfiguration {
fn from(value: RtcConfiguration) -> Self {
Self {
ice_servers: value.ice_servers.into_iter().map(Into::into).collect(),
continual_gathering_policy: value.continual_gathering_policy.into(),
ice_transport_type: value.ice_transport_type.into(),
}
}
}
#[derive(Clone)]
pub struct RTCRuntime {
pub struct RtcRuntime {
pub(crate) sys_handle: SharedPtr<sys_webrtc::ffi::RTCRuntime>,
_logsink: UniquePtr<sys_ls::ffi::LogSink>,
}
impl Default for RTCRuntime {
fn default() -> Self {
Self {
sys_handle: sys_webrtc::ffi::create_rtc_runtime(),
impl RtcRuntime {
pub fn instance() -> Arc<RtcRuntime> {
let mut lk_runtime_ref = RTC_RUNTIME.lock();
if let Some(lk_runtime) = lk_runtime_ref.upgrade() {
lk_runtime
} else {
log::trace!("RtcRuntime::new()");
let new_runtime = Arc::new(Self {
sys_handle: sys_webrtc::ffi::create_rtc_runtime(),
_logsink: sys_ls::ffi::new_log_sink(|msg, severity| {
// Forward logs from webrtc to rust log crate
let msg = msg
.strip_suffix("\r\n")
.or(msg.strip_suffix("\n"))
.unwrap_or(&msg);
let lvl = match severity {
sys_ls::ffi::LoggingSeverity::Verbose => log::Level::Trace,
sys_ls::ffi::LoggingSeverity::Info => log::Level::Debug, // Translte webrtc
// info to debug log level to avoid polluting the user logs
sys_ls::ffi::LoggingSeverity::Warning => log::Level::Warn,
sys_ls::ffi::LoggingSeverity::Error => log::Level::Error,
_ => log::Level::Debug,
};
log::log!(target: "libwebrtc", lvl, "{}", msg);
}),
});
*lk_runtime_ref = Arc::downgrade(&new_runtime);
new_runtime
}
}
}
impl Drop for RtcRuntime {
fn drop(&mut self) {
log::trace!("RtcRuntime::drop()");
}
}
#[derive(Clone)]
pub struct PeerConnectionFactory {
sys_handle: SharedPtr<sys_pcf::ffi::PeerConnectionFactory>,
#[allow(unused)]
runtime: RTCRuntime,
runtime: Arc<RtcRuntime>,
}
impl Default for PeerConnectionFactory {
fn default() -> Self {
let runtime = RTCRuntime::default();
let runtime = RtcRuntime::instance();
Self {
sys_handle: sys_pcf::ffi::create_peer_connection_factory(runtime.sys_handle.clone()),
runtime,
@@ -102,7 +98,7 @@ impl PeerConnectionFactory {
unsafe {
let observer = Arc::new(imp_pc::PeerObserver::default());
let native_observer = sys_pc::ffi::create_native_peer_connection_observer(
self.runtime.clone().sys_handle,
self.runtime.sys_handle.clone(),
Box::new(sys_pc::PeerConnectionObserverWrapper::new(observer.clone())),
);
@@ -155,3 +151,48 @@ impl PeerConnectionFactory {
.into()
}
}
// Conversions
impl From<IceServer> for sys_pcf::ffi::ICEServer {
fn from(value: IceServer) -> Self {
sys_pcf::ffi::ICEServer {
urls: value.urls,
username: value.username,
password: value.password,
}
}
}
impl From<ContinualGatheringPolicy> for sys_pcf::ffi::ContinualGatheringPolicy {
fn from(value: ContinualGatheringPolicy) -> Self {
match value {
ContinualGatheringPolicy::GatherOnce => {
sys_pcf::ffi::ContinualGatheringPolicy::GatherOnce
}
ContinualGatheringPolicy::GatherContinually => {
sys_pcf::ffi::ContinualGatheringPolicy::GatherContinually
}
}
}
}
impl From<IceTransportsType> for sys_pcf::ffi::IceTransportsType {
fn from(value: IceTransportsType) -> Self {
match value {
IceTransportsType::None => sys_pcf::ffi::IceTransportsType::None,
IceTransportsType::Relay => sys_pcf::ffi::IceTransportsType::Relay,
IceTransportsType::NoHost => sys_pcf::ffi::IceTransportsType::NoHost,
IceTransportsType::All => sys_pcf::ffi::IceTransportsType::All,
}
}
}
impl From<RtcConfiguration> for sys_pcf::ffi::RTCConfiguration {
fn from(value: RtcConfiguration) -> Self {
Self {
ice_servers: value.ice_servers.into_iter().map(Into::into).collect(),
continual_gathering_policy: value.continual_gathering_policy.into(),
ice_transport_type: value.ice_transport_type.into(),
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ livekit-protocol = { path = "../livekit-protocol", version = "0.1.0" }
prost = "0.11"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0"
tokio-tungstenite = { version = "0.18", features = ["native-tls"] }
tokio-tungstenite = { version = "0.19", features = ["native-tls"] }
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1"
parking_lot = { version = "0.12.1", features = ["send_guard"] }
+1 -1
View File
@@ -137,7 +137,7 @@ impl LocalAudioTrack {
source: NativeAudioSource,
) -> LocalAudioTrack {
let rtc_track = LkRuntime::instance()
.pc_factory
.pc_factory()
.create_audio_track(&rtc::native::create_random_uuid(), source);
Self::new(name.to_string(), rtc_track, options)
+1 -1
View File
@@ -136,7 +136,7 @@ impl LocalVideoTrack {
source: NativeVideoSource,
) -> LocalVideoTrack {
let rtc_track = LkRuntime::instance()
.pc_factory
.pc_factory()
.create_video_track(&rtc::native::create_random_uuid(), source);
Self::new(name.to_string(), rtc_track, options)
+7 -9
View File
@@ -10,7 +10,7 @@ lazy_static! {
}
pub struct LkRuntime {
pub pc_factory: PeerConnectionFactory,
pc_factory: PeerConnectionFactory,
}
impl Debug for LkRuntime {
@@ -25,19 +25,17 @@ impl LkRuntime {
if let Some(lk_runtime) = lk_runtime_ref.upgrade() {
lk_runtime
} else {
let new_runtime = Arc::new(LkRuntime::default());
trace!("LkRuntime::new()");
let new_runtime = Arc::new(Self {
pc_factory: PeerConnectionFactory::default(),
});
*lk_runtime_ref = Arc::downgrade(&new_runtime);
new_runtime
}
}
}
impl Default for LkRuntime {
fn default() -> Self {
trace!("LkRuntime::default()");
Self {
pc_factory: PeerConnectionFactory::default(),
}
pub fn pc_factory(&self) -> &PeerConnectionFactory {
&self.pc_factory
}
}
+3 -3
View File
@@ -176,14 +176,14 @@ impl RtcSession {
let mut publisher_pc = PeerTransport::new(
lk_runtime
.pc_factory
.pc_factory()
.create_peer_connection(rtc_config.clone())?,
proto::SignalTarget::Publisher,
);
let mut subscriber_pc = PeerTransport::new(
lk_runtime
.pc_factory
.pc_factory()
.create_peer_connection(rtc_config.clone())?,
proto::SignalTarget::Subscriber,
);
@@ -666,7 +666,7 @@ impl SessionInner {
if track.kind() == TrackKind::Video {
let capabilities = LkRuntime::instance()
.pc_factory
.pc_factory()
.get_rtp_sender_capabilities(track.kind().into());
let mut matched = Vec::new();
+2
View File
@@ -150,6 +150,7 @@ fn main() {
"src/yuv_helper.rs",
"src/helper.rs",
"src/audio_resampler.rs",
"src/logsink.rs",
]);
builder.files(&[
@@ -171,6 +172,7 @@ fn main() {
"src/video_decoder_factory.cpp",
"src/audio_device.cpp",
"src/audio_resampler.cpp",
"src/logsink.cpp",
]);
for include in includes {
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright 2023 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "livekit/webrtc.h"
#include "rtc_base/logging.h"
#include "rust/cxx.h"
namespace livekit {
class LogSink;
} // namespace livekit
#include "webrtc-sys/src/logsink.rs.h"
namespace livekit {
class LogSink : public rtc::LogSink {
public:
LogSink(rust::Fn<void(rust::String message, LoggingSeverity severity)> fnc);
~LogSink();
void OnLogMessage(const std::string& message, rtc::LoggingSeverity severity) override;
void OnLogMessage(const std::string& message) override {}
private:
rust::Fn<void(rust::String message, LoggingSeverity severity)> fnc_;
};
std::unique_ptr<LogSink> new_log_sink(rust::Fn<void(rust::String, LoggingSeverity)> fnc);
} // namespace livekit
+1
View File
@@ -3,6 +3,7 @@ pub mod candidate;
pub mod data_channel;
pub mod helper;
pub mod jsep;
pub mod logsink;
pub mod media_stream;
pub mod peer_connection;
pub mod peer_connection_factory;
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright 2023 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <memory>
#include "livekit/logsink.h"
namespace livekit {
LogSink::LogSink(rust::Fn<void(rust::String message, LoggingSeverity severity)> fnc) : fnc_(fnc) {
rtc::LogMessage::AddLogToStream(this, rtc::LoggingSeverity::LS_VERBOSE);
}
LogSink::~LogSink() {
rtc::LogMessage::RemoveLogToStream(this);
}
void LogSink::OnLogMessage(const std::string& message, rtc::LoggingSeverity severity) {
fnc_(rust::String(message), static_cast<LoggingSeverity>(severity));
}
std::unique_ptr<LogSink> new_log_sink(rust::Fn<void (rust::String, LoggingSeverity)> fnc) {
return std::make_unique<LogSink>(fnc);
}
}
+24
View File
@@ -0,0 +1,24 @@
use crate::impl_thread_safety;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
#[derive(Debug)]
#[repr(i32)]
pub enum LoggingSeverity {
Verbose,
Info,
Warning,
Error,
None,
}
unsafe extern "C++" {
include!("livekit/logsink.h");
type LogSink;
fn new_log_sink(fnc: fn(String, LoggingSeverity)) -> UniquePtr<LogSink>;
}
}
impl_thread_safety!(ffi::LogSink, Send + Sync);