feat: add ffi datachannel & mute events (#88)
This commit is contained in:
@@ -1,12 +1,35 @@
|
||||
use crate::imp::audio_source as imp_as;
|
||||
use livekit_protocol::enum_dispatch;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct AudioSourceOptions {
|
||||
pub echo_cancellation: bool,
|
||||
pub noise_suppression: bool,
|
||||
pub auto_gain_control: bool,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RtcAudioSource {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Native(native::NativeAudioSource),
|
||||
}
|
||||
|
||||
impl RtcAudioSource {
|
||||
enum_dispatch!(
|
||||
[Native];
|
||||
fn set_audio_options(self: &Self, options: AudioSourceOptions) -> ();
|
||||
fn audio_options(self: &Self) -> AudioSourceOptions;
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod native {
|
||||
use super::imp_as;
|
||||
use super::*;
|
||||
use crate::audio_frame::AudioFrame;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct NativeAudioSource {
|
||||
pub(crate) handle: imp_as::NativeAudioSource,
|
||||
}
|
||||
@@ -17,9 +40,29 @@ pub mod native {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NativeAudioSource {
|
||||
fn default() -> Self {
|
||||
Self::new(AudioSourceOptions::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeAudioSource {
|
||||
pub fn new(options: AudioSourceOptions) -> NativeAudioSource {
|
||||
Self {
|
||||
handle: imp_as::NativeAudioSource::new(options),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capture_frame(&self, frame: &AudioFrame) {
|
||||
self.handle.capture_frame(frame)
|
||||
}
|
||||
|
||||
pub fn set_audio_options(&self, options: AudioSourceOptions) {
|
||||
self.handle.set_audio_options(options)
|
||||
}
|
||||
|
||||
pub fn audio_options(&self) -> AudioSourceOptions {
|
||||
self.handle.audio_options()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,29 @@
|
||||
use crate::audio_frame::AudioFrame;
|
||||
use crate::{audio_frame::AudioFrame, audio_source::AudioSourceOptions};
|
||||
use cxx::SharedPtr;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
use webrtc_sys::audio_track as sys_at;
|
||||
|
||||
impl From<sys_at::ffi::AudioSourceOptions> for AudioSourceOptions {
|
||||
fn from(options: sys_at::ffi::AudioSourceOptions) -> Self {
|
||||
Self {
|
||||
echo_cancellation: options.echo_cancellation,
|
||||
noise_suppression: options.noise_suppression,
|
||||
auto_gain_control: options.auto_gain_control,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AudioSourceOptions> for sys_at::ffi::AudioSourceOptions {
|
||||
fn from(options: AudioSourceOptions) -> Self {
|
||||
Self {
|
||||
echo_cancellation: options.echo_cancellation,
|
||||
noise_suppression: options.noise_suppression,
|
||||
auto_gain_control: options.auto_gain_control,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NativeAudioSource {
|
||||
sys_handle: SharedPtr<sys_at::ffi::AudioTrackSource>,
|
||||
@@ -18,20 +38,27 @@ struct AudioSourceInner {
|
||||
num_channels: u32,
|
||||
}
|
||||
|
||||
impl Default for NativeAudioSource {
|
||||
fn default() -> Self {
|
||||
impl NativeAudioSource {
|
||||
pub fn new(options: AudioSourceOptions) -> NativeAudioSource {
|
||||
Self {
|
||||
sys_handle: sys_at::ffi::new_audio_track_source(),
|
||||
sys_handle: sys_at::ffi::new_audio_track_source(options.into()),
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeAudioSource {
|
||||
pub fn sys_handle(&self) -> SharedPtr<sys_at::ffi::AudioTrackSource> {
|
||||
self.sys_handle.clone()
|
||||
}
|
||||
|
||||
pub fn set_audio_options(&self, options: AudioSourceOptions) {
|
||||
self.sys_handle
|
||||
.set_audio_options(&sys_at::ffi::AudioSourceOptions::from(options))
|
||||
}
|
||||
|
||||
pub fn audio_options(&self) -> AudioSourceOptions {
|
||||
self.sys_handle.audio_options().into()
|
||||
}
|
||||
|
||||
pub fn capture_frame(&self, frame: &AudioFrame) {
|
||||
let mut inner = self.inner.lock();
|
||||
let samples_10ms = (frame.sample_rate / 100 * frame.num_channels) as usize;
|
||||
|
||||
@@ -1,22 +1,42 @@
|
||||
use crate::video_frame::{VideoFrame, VideoFrameBuffer};
|
||||
use crate::video_source::VideoResolution;
|
||||
use cxx::SharedPtr;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use webrtc_sys::video_frame as vf_sys;
|
||||
use webrtc_sys::video_track as vt_sys;
|
||||
|
||||
impl From<vt_sys::ffi::VideoResolution> for VideoResolution {
|
||||
fn from(res: vt_sys::ffi::VideoResolution) -> Self {
|
||||
Self {
|
||||
width: res.width,
|
||||
height: res.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VideoResolution> for vt_sys::ffi::VideoResolution {
|
||||
fn from(res: VideoResolution) -> Self {
|
||||
Self {
|
||||
width: res.width,
|
||||
height: res.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NativeVideoSource {
|
||||
sys_handle: SharedPtr<vt_sys::ffi::VideoTrackSource>,
|
||||
}
|
||||
|
||||
impl Default for NativeVideoSource {
|
||||
fn default() -> Self {
|
||||
impl NativeVideoSource {
|
||||
pub fn new(resolution: VideoResolution) -> NativeVideoSource {
|
||||
Self {
|
||||
sys_handle: vt_sys::ffi::new_video_track_source(),
|
||||
sys_handle: vt_sys::ffi::new_video_track_source(&vt_sys::ffi::VideoResolution::from(
|
||||
resolution,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeVideoSource {
|
||||
pub fn sys_handle(&self) -> SharedPtr<vt_sys::ffi::VideoTrackSource> {
|
||||
self.sys_handle.clone()
|
||||
}
|
||||
@@ -27,7 +47,20 @@ impl NativeVideoSource {
|
||||
builder
|
||||
.pin_mut()
|
||||
.set_video_frame_buffer(frame.buffer.as_ref().sys_handle());
|
||||
|
||||
if frame.timestamp_us == 0 {
|
||||
// If the timestamp is set to 0, default to now
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||
builder.pin_mut().set_timestamp_us(now.as_micros() as i64);
|
||||
} else {
|
||||
builder.pin_mut().set_timestamp_us(frame.timestamp_us);
|
||||
}
|
||||
|
||||
self.sys_handle
|
||||
.on_captured_frame(&builder.pin_mut().build());
|
||||
}
|
||||
|
||||
pub fn video_resolution(&self) -> VideoResolution {
|
||||
self.sys_handle.video_resolution().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ impl sys_vt::VideoSink for VideoTrackObserver {
|
||||
fn on_frame(&self, frame: UniquePtr<webrtc_sys::video_frame::ffi::VideoFrame>) {
|
||||
let _ = self.frame_tx.send(VideoFrame {
|
||||
rotation: frame.rotation().into(),
|
||||
timestamp: frame.timestamp_us(),
|
||||
timestamp_us: frame.timestamp_us(),
|
||||
buffer: new_video_frame_buffer(unsafe { frame.video_frame_buffer() }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pub use crate::audio_frame::AudioFrame;
|
||||
pub use crate::audio_source::{AudioSourceOptions, RtcAudioSource};
|
||||
pub use crate::audio_track::RtcAudioTrack;
|
||||
pub use crate::data_channel::{
|
||||
DataBuffer, DataChannel, DataChannelError, DataChannelInit, DataState,
|
||||
@@ -22,5 +23,6 @@ pub use crate::video_frame::{
|
||||
BoxVideoFrame, I010Buffer, I420ABuffer, I420Buffer, I422Buffer, I444Buffer, NV12Buffer,
|
||||
VideoFormatType, VideoFrame, VideoFrameBuffer, VideoFrameBufferType, VideoRotation,
|
||||
};
|
||||
pub use crate::video_source::{RtcVideoSource, VideoResolution};
|
||||
pub use crate::video_track::RtcVideoTrack;
|
||||
pub use crate::{MediaType, RtcError, RtcErrorType};
|
||||
|
||||
@@ -43,7 +43,7 @@ where
|
||||
T: AsRef<dyn VideoFrameBuffer>,
|
||||
{
|
||||
pub rotation: VideoRotation,
|
||||
pub timestamp: i64, // When the frame was captured
|
||||
pub timestamp_us: i64, // When the frame was captured in microseconds
|
||||
pub buffer: T,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,36 @@
|
||||
use livekit_protocol::enum_dispatch;
|
||||
|
||||
use crate::imp::video_source as vs_imp;
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct VideoResolution {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RtcVideoSource {
|
||||
// TODO(theomonnom): Web video sources (eq. to tracks on browsers?)
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Native(native::NativeVideoSource),
|
||||
}
|
||||
|
||||
// TODO(theomonnom): Support enum dispatch with conditional compilation?
|
||||
impl RtcVideoSource {
|
||||
enum_dispatch!(
|
||||
[Native];
|
||||
pub fn video_resolution(self: &Self) -> VideoResolution;
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod native {
|
||||
use super::vs_imp;
|
||||
use super::*;
|
||||
use crate::video_frame::{VideoFrame, VideoFrameBuffer};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct NativeVideoSource {
|
||||
pub(crate) handle: vs_imp::NativeVideoSource,
|
||||
}
|
||||
@@ -17,10 +41,26 @@ pub mod native {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NativeVideoSource {
|
||||
fn default() -> Self {
|
||||
Self::new(VideoResolution::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeVideoSource {
|
||||
pub fn new(resolution: VideoResolution) -> Self {
|
||||
Self {
|
||||
handle: vs_imp::NativeVideoSource::new(resolution),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capture_frame<T: AsRef<dyn VideoFrameBuffer>>(&self, frame: &VideoFrame<T>) {
|
||||
self.handle.capture_frame(frame)
|
||||
}
|
||||
|
||||
pub fn video_resolution(&self) -> VideoResolution {
|
||||
self.handle.video_resolution()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user