RtpTransceiver bindings & requirements for publishing tracks (#39)

- RtpSender
- RtpReceiver
- RtpTransceiver
- RtpParameters
- VideoFrameBuilder
- Interior mutability on c++ side
- Cleanup bindings ( Use #pragma once instead of include guards )
     - webrtc-sys/src/* headers are now used in only one place 
     - Avoid confusion between generated headers and our headers
- AdaptedVideoTrackSource
- Cleanup the workaround with unsupported Vec<Shared<T>>
    - Put everything inside one file
This commit is contained in:
Théo Monnom
2023-02-12 19:44:04 +01:00
committed by GitHub
parent 4411f88b68
commit 16ea02075f
64 changed files with 3357 additions and 670 deletions
+100 -111
View File
@@ -1,7 +1,6 @@
use cxx::UniquePtr;
use cxx::{SharedPtr, UniquePtr};
use livekit_utils::enum_dispatch;
use std::fmt::{Debug, Formatter};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use webrtc_sys::media_stream as sys_ms;
use webrtc_sys::MEDIA_TYPE_VIDEO;
@@ -27,19 +26,19 @@ pub enum MediaStreamTrackHandle {
}
impl MediaStreamTrackHandle {
pub(crate) fn new(cxx_handle: UniquePtr<sys_ms::ffi::MediaStreamTrack>) -> Self {
unsafe {
if cxx_handle.kind() == MEDIA_TYPE_VIDEO {
Self::Video(VideoTrack::new(UniquePtr::from_raw(
sys_ms::ffi::media_to_video(cxx_handle.into_raw())
as *mut sys_ms::ffi::VideoTrack,
)))
} else {
Self::Audio(AudioTrack::new(UniquePtr::from_raw(
sys_ms::ffi::media_to_audio(cxx_handle.into_raw())
as *mut sys_ms::ffi::AudioTrack,
)))
}
pub(crate) fn new(cxx_handle: SharedPtr<sys_ms::ffi::MediaStreamTrack>) -> Self {
if cxx_handle.kind() == MEDIA_TYPE_VIDEO {
Self::Video(VideoTrack::new(cxx_handle))
} else {
Self::Audio(AudioTrack::new(cxx_handle))
}
}
// TODO(theomonnom): enum_dispatch with visibility support?
pub(crate) fn cxx_handle(&self) -> SharedPtr<sys_ms::ffi::MediaStreamTrack> {
match self {
Self::Video(video) => video.cxx_handle(),
Self::Audio(audio) => audio.cxx_handle(),
}
}
}
@@ -67,58 +66,123 @@ impl MediaStreamTrackTrait for MediaStreamTrackHandle {
}
pub struct AudioTrack {
cxx_handle: Mutex<UniquePtr<sys_ms::ffi::AudioTrack>>,
cxx_handle: SharedPtr<sys_ms::ffi::MediaStreamTrack>,
}
impl AudioTrack {
pub(crate) fn new(cxx_handle: UniquePtr<sys_ms::ffi::AudioTrack>) -> Arc<Self> {
Arc::new(Self {
cxx_handle: Mutex::new(cxx_handle),
})
fn new(cxx_handle: SharedPtr<sys_ms::ffi::MediaStreamTrack>) -> Arc<Self> {
Arc::new(Self { cxx_handle })
}
pub(crate) fn cxx_handle(&self) -> SharedPtr<sys_ms::ffi::MediaStreamTrack> {
self.cxx_handle.clone()
}
}
pub struct VideoTrack {
cxx_handle: Mutex<UniquePtr<sys_ms::ffi::VideoTrack>>,
cxx_handle: SharedPtr<sys_ms::ffi::MediaStreamTrack>,
observer: Box<InternalVideoTrackSink>,
// Keep alive for c++
native_observer: UniquePtr<sys_ms::ffi::NativeVideoFrameSink>,
}
impl VideoTrack {
fn new(cxx_handle: SharedPtr<sys_ms::ffi::MediaStreamTrack>) -> Arc<Self> {
let mut observer = Box::new(InternalVideoTrackSink::default());
let mut track = unsafe {
Self {
cxx_handle,
native_observer: {
sys_ms::ffi::create_native_video_frame_sink(Box::new(
sys_ms::VideoFrameSinkWrapper::new(&mut *observer),
))
},
observer,
}
};
unsafe {
(*track.video_handle()).add_sink(track.native_observer.pin_mut());
}
Arc::new(track)
}
pub(crate) fn cxx_handle(&self) -> SharedPtr<sys_ms::ffi::MediaStreamTrack> {
self.cxx_handle.clone()
}
fn video_handle(&self) -> *const sys_ms::ffi::VideoTrack {
unsafe { sys_ms::ffi::media_to_video(&*self.cxx_handle) }
}
pub fn set_should_receive(&self, should_receive: bool) {
unsafe { (*self.video_handle()).set_should_receive(should_receive) }
}
pub fn set_content_hint(&self, hint: ContentHint) {
unsafe { (*self.video_handle()).set_content_hint(hint) }
}
pub fn should_receive(&self) -> bool {
unsafe { (*self.video_handle()).should_receive() }
}
pub fn content_hint(&self) -> ContentHint {
unsafe { (*self.video_handle()).content_hint() }
}
pub fn on_frame(&self, handler: OnFrameHandler) {
*self.observer.on_frame_handler.lock().unwrap() = Some(handler);
}
pub fn on_discarded_frame(&self, handler: OnDiscardedFrameHandler) {
*self.observer.on_discarded_frame_handler.lock().unwrap() = Some(handler);
}
pub fn on_constraints_changed(&self, handler: OnConstraintsChangedHandler) {
*self.observer.on_constraints_changed_handler.lock().unwrap() = Some(handler);
}
}
impl Drop for VideoTrack {
fn drop(&mut self) {
unsafe {
(*self.video_handle()).remove_sink(self.native_observer.pin_mut());
}
}
}
macro_rules! impl_media_stream_track_trait {
($x:ty, $cast:ident) => {
($x:ty) => {
impl MediaStreamTrackTrait for $x {
fn kind(&self) -> String {
unsafe { (*sys_ms::ffi::$cast(&**self.cxx_handle.lock().unwrap())).kind() }
self.cxx_handle.kind()
}
fn id(&self) -> String {
unsafe { (*sys_ms::ffi::$cast(&**self.cxx_handle.lock().unwrap())).id() }
self.cxx_handle.id()
}
fn enabled(&self) -> bool {
unsafe { (*sys_ms::ffi::$cast(&**self.cxx_handle.lock().unwrap())).enabled() }
self.cxx_handle.enabled()
}
fn set_enabled(&self, enabled: bool) -> bool {
unsafe {
let media = sys_ms::ffi::$cast(&**self.cxx_handle.lock().unwrap())
as *mut sys_ms::ffi::MediaStreamTrack;
Pin::new_unchecked(&mut *media).set_enabled(enabled)
}
self.cxx_handle.set_enabled(enabled)
}
fn state(&self) -> TrackState {
unsafe { (*sys_ms::ffi::$cast(&**self.cxx_handle.lock().unwrap())).state() }
self.cxx_handle.state()
}
}
};
}
impl_media_stream_track_trait!(VideoTrack, video_to_media);
impl_media_stream_track_trait!(AudioTrack, audio_to_media);
impl_media_stream_track_trait!(VideoTrack);
impl_media_stream_track_trait!(AudioTrack);
pub type OnFrameHandler = Box<dyn FnMut(VideoFrame, VideoFrameBuffer) + Send + Sync>;
pub type OnDiscardedFrameHandler = Box<dyn FnMut() + Send + Sync>;
@@ -167,83 +231,8 @@ impl sys_ms::VideoFrameSink for InternalVideoTrackSink {
}
}
impl VideoTrack {
fn new(cxx_handle: UniquePtr<sys_ms::ffi::VideoTrack>) -> Arc<Self> {
let mut observer = Box::new(InternalVideoTrackSink::default());
let mut track = unsafe {
Self {
cxx_handle: Mutex::new(cxx_handle),
native_observer: sys_ms::ffi::create_native_video_frame_sink(Box::new(
sys_ms::VideoFrameSinkWrapper::new(&mut *observer),
)),
observer,
}
};
unsafe {
track
.cxx_handle
.lock()
.unwrap()
.pin_mut()
.add_sink(track.native_observer.pin_mut());
}
Arc::new(track)
}
pub fn set_should_receive(&self, should_receive: bool) {
self.cxx_handle
.lock()
.unwrap()
.pin_mut()
.set_should_receive(should_receive)
}
pub fn set_content_hint(&self, hint: ContentHint) {
self.cxx_handle
.lock()
.unwrap()
.pin_mut()
.set_content_hint(hint)
}
pub fn should_receive(&self) -> bool {
self.cxx_handle.lock().unwrap().should_receive()
}
pub fn content_hint(&self) -> ContentHint {
self.cxx_handle.lock().unwrap().content_hint()
}
pub fn on_frame(&self, handler: OnFrameHandler) {
*self.observer.on_frame_handler.lock().unwrap() = Some(handler);
}
pub fn on_discarded_frame(&self, handler: OnDiscardedFrameHandler) {
*self.observer.on_discarded_frame_handler.lock().unwrap() = Some(handler);
}
pub fn on_constraints_changed(&self, handler: OnConstraintsChangedHandler) {
*self.observer.on_constraints_changed_handler.lock().unwrap() = Some(handler);
}
}
impl Drop for VideoTrack {
fn drop(&mut self) {
unsafe {
self.cxx_handle
.lock()
.unwrap()
.pin_mut()
.remove_sink(self.native_observer.pin_mut());
}
}
}
pub struct MediaStream {
cxx_handle: UniquePtr<sys_ms::ffi::MediaStream>,
cxx_handle: SharedPtr<sys_ms::ffi::MediaStream>,
}
impl Debug for MediaStream {
@@ -255,7 +244,7 @@ impl Debug for MediaStream {
}
impl MediaStream {
pub(crate) fn new(cxx_handle: UniquePtr<sys_ms::ffi::MediaStream>) -> Self {
pub(crate) fn new(cxx_handle: SharedPtr<sys_ms::ffi::MediaStream>) -> Self {
Self { cxx_handle }
}