livekit-utils crate + VideoRenderer proto

This commit is contained in:
Théo Monnom
2022-12-02 16:39:42 +01:00
parent 59e7ccbffe
commit 686f5db969
30 changed files with 2208 additions and 87 deletions
+2 -1
View File
@@ -5,6 +5,8 @@ edition = "2021"
license = "Apache-2.0"
[dependencies]
livekit-webrtc = { path = "../livekit-webrtc" }
livekit-utils = { path = "../livekit-utils" }
serde = { version = "1", features = ["derive"] }
serde_json = "1.0"
tokio-tungstenite = { version = "0.17.2", features = ["native-tls"] }
@@ -16,7 +18,6 @@ futures-util = "0.3.23"
thiserror = "1.0"
prost = "0.11.0"
prost-types = "0.11.1"
livekit-webrtc = { path = "../livekit-webrtc" }
lazy_static = "1.4.0"
tracing = "0.1"
-1
View File
@@ -7,6 +7,5 @@ pub mod proto {
mod events;
mod rtc_engine;
mod signal_client;
mod utils;
pub mod room;
+10 -10
View File
@@ -4,8 +4,8 @@ use crate::room::id::{ParticipantIdentity, ParticipantSid, TrackSid};
use crate::room::participant::local_participant::LocalParticipant;
use crate::room::participant::remote_participant::RemoteParticipant;
use crate::room::publication::{TrackPublication, TrackPublicationTrait};
use crate::utils::wrap_variants;
use futures_util::future::BoxFuture;
use livekit_utils::enum_dispatch;
use parking_lot::{Mutex, RwLock};
use std::collections::HashMap;
use std::sync::Arc;
@@ -74,7 +74,7 @@ pub enum ParticipantHandle {
}
impl ParticipantHandle {
// TODO(theomonnom): Add async support to wrap_variants ...
// TODO(theomonnom): Add async support to wrap_variants ...
pub(crate) async fn update_info(&self, info: ParticipantInfo) {
match self {
Self::Local(inner) => inner.clone().update_info(info).await,
@@ -84,20 +84,20 @@ impl ParticipantHandle {
}
impl ParticipantInternalTrait for ParticipantHandle {
wrap_variants!(
enum_dispatch!(
[Local, Remote]
fnc!(internal_events, Arc<ParticipantEvents>, []);
fnc!(internal_events, &Self, [], Arc<ParticipantEvents>);
);
}
impl ParticipantTrait for ParticipantHandle {
wrap_variants!(
enum_dispatch!(
[Local, Remote]
fnc!(events, Arc<ParticipantEvents>, []);
fnc!(sid, ParticipantSid, []);
fnc!(identity, ParticipantIdentity, []);
fnc!(name, String, []);
fnc!(metadata, String, []);
fnc!(events, &Self, [], Arc<ParticipantEvents>);
fnc!(sid, &Self, [], ParticipantSid);
fnc!(identity, &Self, [], ParticipantIdentity);
fnc!(name, &Self, [], String);
fnc!(metadata, &Self, [], String);
);
}
+15 -11
View File
@@ -5,7 +5,7 @@ use crate::room::id::TrackSid;
use crate::room::track::local_track::LocalTrackHandle;
use crate::room::track::remote_track::RemoteTrackHandle;
use crate::room::track::{TrackHandle, TrackKind, TrackSource};
use crate::utils::wrap_variants;
use livekit_utils::enum_dispatch;
use parking_lot::Mutex;
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::Arc;
@@ -38,7 +38,11 @@ pub(super) struct TrackPublicationShared {
}
impl TrackPublicationShared {
pub fn new(info: TrackInfo, participant: ParticipantSid, track: Option<TrackHandle>) -> Arc<Self> {
pub fn new(
info: TrackInfo,
participant: ParticipantSid,
track: Option<TrackHandle>,
) -> Arc<Self> {
Arc::new(Self {
track: Mutex::new(track),
name: Mutex::new(info.name),
@@ -88,21 +92,21 @@ impl TrackPublication {
}
impl TrackPublicationInternalTrait for TrackPublication {
wrap_variants!(
enum_dispatch!(
[Local, Remote]
fnc!(update_track, (), [track: Option<TrackHandle>]);
fnc!(update_info, (), [info: TrackInfo]);
fnc!(update_track, &Self, [track: Option<TrackHandle>], ());
fnc!(update_info, &Self, [info: TrackInfo], ());
);
}
impl TrackPublicationTrait for TrackPublication {
wrap_variants!(
enum_dispatch!(
[Local, Remote]
fnc!(sid, TrackSid, []);
fnc!(name, String, []);
fnc!(kind, TrackKind, []);
fnc!(source, TrackSource, []);
fnc!(simulcasted, bool, []);
fnc!(sid, &Self, [], TrackSid);
fnc!(name, &Self, [], String);
fnc!(kind, &Self, [], TrackKind);
fnc!(source, &Self, [], TrackSource);
fnc!(simulcasted, &Self, [], bool);
);
}
+8 -8
View File
@@ -4,7 +4,7 @@ use crate::room::track::local_audio_track::LocalAudioTrack;
use crate::room::track::local_video_track::LocalVideoTrack;
use crate::room::track::remote_audio_track::RemoteAudioTrack;
use crate::room::track::remote_video_track::RemoteVideoTrack;
use crate::utils::wrap_variants;
use livekit_utils::enum_dispatch;
use livekit_webrtc::media_stream::{MediaStreamTrackHandle, MediaStreamTrackTrait};
use parking_lot::Mutex;
use std::sync::atomic::AtomicU8;
@@ -150,14 +150,14 @@ pub enum TrackHandle {
}
impl TrackTrait for TrackHandle {
wrap_variants!(
enum_dispatch!(
[LocalVideo, LocalAudio, RemoteVideo, RemoteAudio]
fnc!(sid, TrackSid, []);
fnc!(name, String, []);
fnc!(kind, TrackKind, []);
fnc!(stream_state, StreamState, []);
fnc!(start, (), []);
fnc!(stop, (), []);
fnc!(sid, &Self, [], TrackSid);
fnc!(name, &Self, [], String);
fnc!(kind, &Self, [], TrackKind);
fnc!(stream_state, &Self, [], StreamState);
fnc!(start, &Self, [], ());
fnc!(stop, &Self, [], ());
);
}
@@ -5,7 +5,7 @@ use crate::room::id::TrackSid;
use crate::room::track::remote_audio_track::RemoteAudioTrack;
use crate::room::track::remote_video_track::RemoteVideoTrack;
use crate::room::track::TrackHandle;
use crate::utils::wrap_variants;
use livekit_utils::enum_dispatch;
use super::TrackTrait;
@@ -16,14 +16,14 @@ pub enum RemoteTrackHandle {
}
impl TrackTrait for RemoteTrackHandle {
wrap_variants!(
enum_dispatch!(
[Audio, Video]
fnc!(sid, TrackSid, []);
fnc!(name, String, []);
fnc!(kind, TrackKind, []);
fnc!(stream_state, StreamState, []);
fnc!(start, (), []);
fnc!(stop, (), []);
fnc!(sid, &Self, [], TrackSid);
fnc!(name, &Self, [], String);
fnc!(kind, &Self, [], TrackKind);
fnc!(stream_state, &Self, [], StreamState);
fnc!(start, &Self, [], ());
fnc!(stop, &Self, [], ());
);
}
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "livekit-utils"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@@ -1,4 +1,5 @@
macro_rules! wrap_variants {
#[macro_export]
macro_rules! enum_dispatch {
// This arm is used to avoid nested loops with the arguments
// The arguments are transformed to $combined_args TokenTree
(@match $self:ident $fnc:ident $combined_args:tt [$($variant:ident),+]) => {
@@ -9,18 +10,16 @@ macro_rules! wrap_variants {
}
};
($fnc:ident, $ret:ty, [$($arg:ident: $t:ty),*], [$($variant:ident),+]) => {
fn $fnc(&self, $($arg: $t),*) -> $ret {
wrap_variants!(@match self $fnc ($($arg,)*) [$($variant),+])
($fnc:ident, $self:ty, [$($arg:ident: $t:ty),*], $ret:ty, [$($variant:ident),+]) => {
fn $fnc(self: $self, $($arg: $t),*) -> $ret {
enum_dispatch!(@match self $fnc ($($arg,)*) [$($variant),+])
}
};
($variants:tt $(fnc!($fnc:ident, $ret:ty, $args:tt);)+) => {
($variants:tt $(fnc!($fnc:ident, $self:ty, $args:tt, $ret:ty);)+) => {
$(
wrap_variants!($fnc, $ret, $args, $variants);
enum_dispatch!($fnc, $self, $args, $ret, $variants);
)*
};
}
pub(crate) use wrap_variants;
+1
View File
@@ -0,0 +1 @@
pub mod enum_dispatch;
+2 -1
View File
@@ -6,10 +6,11 @@ homepage = "https://livekit.io"
[dependencies]
libwebrtc-sys = { path = "./libwebrtc-sys" }
livekit-utils = { path = "../livekit-utils" }
tokio = { version = "1", features = ["full"] }
cxx = "1.0"
log = "0.4"
thiserror = "1.0"
[dev-dependencies]
env_logger = "0.9"
env_logger = "0.9"
@@ -1,2 +1 @@
/libwebrtc
/cmake-build-debug
+14 -7
View File
@@ -55,17 +55,17 @@ fn main() {
let target_os = "windows";
//let target_arch = "arm64";
let libwebrtc_dir = path::PathBuf::from("libwebrtc");
let libwebrtc_dir = path::PathBuf::from("libwebrtc/src");
// Just required for the bridge build to succeed.
let includes = &[
path::PathBuf::from("./include"),
libwebrtc_dir.join("include/"),
libwebrtc_dir.join("include/third_party/abseil-cpp/"),
libwebrtc_dir.join("include/third_party/libc++/"),
libwebrtc_dir.clone(),
libwebrtc_dir.join("third_party/abseil-cpp/"),
libwebrtc_dir.join("third_party/libc++/"),
// For mac & ios
libwebrtc_dir.join("include/sdk/objc"),
libwebrtc_dir.join("include/sdk/objc/base"),
libwebrtc_dir.join("sdk/objc"),
libwebrtc_dir.join("sdk/objc/base"),
];
let mut builder = cxx_build::bridges(&[
@@ -81,6 +81,7 @@ fn main() {
"src/webrtc.rs",
"src/video_frame.rs",
"src/video_frame_buffer.rs",
"src/yuv_helper.rs",
]);
builder.file("src/peer_connection.cpp");
@@ -100,7 +101,12 @@ fn main() {
println!(
"cargo:rustc-link-search=native={}",
libwebrtc_dir.canonicalize().unwrap().to_str().unwrap()
libwebrtc_dir
.join("out/Default/obj")
.canonicalize()
.unwrap()
.to_str()
.unwrap()
);
match target_os {
@@ -124,6 +130,7 @@ fn main() {
.flag("/std:c++17")
.flag("/EHsc")
.define("WEBRTC_WIN", None)
//.define("WEBRTC_ENABLE_SYMBOL_EXPORT", None) Not necessary when using WebRTC as a static library
.define("NOMINMAX", None);
}
"macos" => {
@@ -1,8 +1,8 @@
-xc++
-std=c++17
-Iinclude
-Ilibwebrtc/include
-Ilibwebrtc/include/third_party/abseil-cpp
-Ilibwebrtc/include/third_party/libc++
-Ilibwebrtc/src
-Ilibwebrtc/src/third_party/abseil-cpp
-Ilibwebrtc/src/third_party/libc++
-I../../../target/cxxbridge
-DWEBRTC_WIN
@@ -0,0 +1,30 @@
//
// Created by Théo Monnom on 01/12/2022.
//
#ifndef CLIENT_SDK_NATIVE_YUV_HELPER_H
#define CLIENT_SDK_NATIVE_YUV_HELPER_H
#include <memory>
#include "api/video/yuv_helper.h"
namespace livekit {
static void i420_to_abgr(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgba,
int dst_stride_abgr,
int width,
int height) {
webrtc::I420ToABGR(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgba, dst_stride_abgr, width, height);
}
} // namespace livekit
#endif // CLIENT_SDK_NATIVE_YUV_HELPER_H
@@ -0,0 +1,11 @@
solutions = [
{
"name" : 'src',
"url" : 'https://github.com/webrtc-sdk/webrtc.git',
"deps_file" : 'DEPS',
"managed" : False,
"custom_deps" : {
},
"custom_vars": {},
},
]
@@ -0,0 +1,3 @@
.cipd
src
.gclient_*
@@ -0,0 +1,19 @@
import subprocess
GN_ARGS = [
"is_debug=false",
"treat_warnings_as_errors=false",
'target_os="win"',
'target_cpu="x64"',
"rtc_include_tests=false",
"rtc_use_h264=false",
"is_component_build=false",
"rtc_build_examples=false",
"use_rtti=true",
"rtc_build_tools=false",
"use_custom_libcxx=false",
"strip_debug_info=true",
"symbol_level=0"
]
subprocess.call(["gn", "gen", "out/Default", "--args=" + ' '.join(GN_ARGS)], shell=True)
@@ -10,6 +10,7 @@ pub mod rtp_transceiver;
pub mod video_frame;
pub mod video_frame_buffer;
pub mod webrtc;
pub mod yuv_helper;
pub const MEDIA_TYPE_VIDEO: &str = "video";
pub const MEDIA_TYPE_AUDIO: &str = "audio";
@@ -0,0 +1,19 @@
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
unsafe extern "C++" {
include!("livekit/yuv_helper.h");
unsafe fn i420_to_abgr(
src_y: *const u8,
src_stride_y: i32,
src_u: *const u8,
src_stride_u: i32,
src_v: *const u8,
src_stride_v: i32,
dst_abgr: *mut u8,
dst_stride_abgr: i32,
width: i32,
height: i32,
);
}
}
+1
View File
@@ -9,3 +9,4 @@ pub mod rtp_transceiver;
pub mod video_frame;
pub mod video_frame_buffer;
pub mod webrtc;
pub mod yuv_helper;
@@ -1,5 +1,6 @@
use cxx::UniquePtr;
use libwebrtc_sys::video_frame_buffer as vfb_sys;
use livekit_utils::enum_dispatch;
use std::pin::Pin;
use std::slice;
use vfb_sys::ffi::VideoFrameBufferType;
@@ -53,6 +54,15 @@ impl VideoFrameBuffer {
}
}
impl VideoFrameBufferTrait for VideoFrameBuffer {
enum_dispatch!(
[Native, I420, I420A, I422, I444, I010, NV12]
fnc!(width, &Self, [], i32);
fnc!(height, &Self, [], i32);
fnc!(to_i420, Self, [], I420Buffer);
);
}
macro_rules! recursive_cast {
($ptr:expr $(, $fnc:ident)*) => {
{
@@ -146,21 +156,23 @@ macro_rules! impl_yuv8_buffer {
fn data_y(&self) -> &[u8] {
let ptr = recursive_cast!(&*self.cxx_handle $(, $cast)*);
unsafe {
slice::from_raw_parts((*ptr).data_y(), self.stride_y().try_into().unwrap())
slice::from_raw_parts((*ptr).data_y(), (self.width() * self.height()) as usize)
}
}
fn data_u(&self) -> &[u8] {
let ptr = recursive_cast!(&*self.cxx_handle $(, $cast)*);
unsafe {
slice::from_raw_parts((*ptr).data_u(), self.stride_u().try_into().unwrap())
let chroma_height = (self.height() + 1) / 2;
slice::from_raw_parts((*ptr).data_u(), (self.stride_u() * chroma_height) as usize)
}
}
fn data_v(&self) -> &[u8] {
let ptr = recursive_cast!(&*self.cxx_handle $(, $cast)*);
unsafe {
slice::from_raw_parts((*ptr).data_v(), self.stride_v().try_into().unwrap())
let chroma_height = (self.height() + 1) / 2;
slice::from_raw_parts((*ptr).data_v(), (self.stride_v() * chroma_height) as usize)
}
}
}
+43
View File
@@ -0,0 +1,43 @@
use std::convert::TryInto;
use libwebrtc_sys::yuv_helper as yuv_sys;
pub fn i420_to_abgr(
src_y: &[u8],
src_stride_y: i32,
src_u: &[u8],
src_stride_u: i32,
src_v: &[u8],
src_stride_v: i32,
dst_abgr: &mut [u8],
dst_stride_abgr: i32,
width: i32,
height: i32,
) {
// Assert minimum capacity for safety
let chroma_height = (height + 1) / 2; // the buffer should be padded?
let min_y: usize = (src_stride_y * height).try_into().unwrap();
let min_u: usize = (src_stride_u * chroma_height).try_into().unwrap();
let min_v: usize = (src_stride_v * chroma_height).try_into().unwrap();
let min_abgr: usize = (dst_stride_abgr * height).try_into().unwrap();
assert!(src_y.len() >= min_y);
assert!(src_u.len() >= min_u);
assert!(src_v.len() >= min_v);
assert!(dst_abgr.len() >= min_abgr);
unsafe {
yuv_sys::ffi::i420_to_abgr(
src_y.as_ptr(),
src_stride_y,
src_u.as_ptr(),
src_stride_u,
src_v.as_ptr(),
src_stride_v,
dst_abgr.as_mut_ptr(),
dst_stride_abgr,
width,
height,
);
}
}