feat: video publishing (#42)

- Prepare webrtc abstraction ( for future wasm support )
- Added track publish support for videos
  - Added LogoTrack example to simple_room demo
- Lot of cleanup
- There are compiler warnings I'll solve on our v1 release
This commit is contained in:
Théo Monnom
2023-03-18 03:25:16 +01:00
committed by GitHub
parent 4443eae434
commit cad6d36201
123 changed files with 8534 additions and 4601 deletions
+16 -9
View File
@@ -18,6 +18,8 @@
#include <utility>
#include "webrtc-sys/src/data_channel.rs.h"
namespace livekit {
DataChannel::DataChannel(
@@ -26,8 +28,8 @@ DataChannel::DataChannel(
: rtc_runtime_(std::move(rtc_runtime)),
data_channel_(std::move(data_channel)) {}
void DataChannel::register_observer(NativeDataChannelObserver& observer) const {
data_channel_->RegisterObserver(&observer);
void DataChannel::register_observer(NativeDataChannelObserver* observer) const {
data_channel_->RegisterObserver(observer);
}
void DataChannel::unregister_observer() const {
@@ -58,7 +60,6 @@ std::unique_ptr<NativeDataChannelInit> create_data_channel_init(
rtc_init->negotiated = init.negotiated;
rtc_init->ordered = init.ordered;
rtc_init->protocol = init.protocol.c_str();
rtc_init->reliable = init.reliable;
if (init.has_max_retransmit_time)
rtc_init->maxRetransmitTime = init.max_retransmit_time;
@@ -73,11 +74,16 @@ std::unique_ptr<NativeDataChannelInit> create_data_channel_init(
}
NativeDataChannelObserver::NativeDataChannelObserver(
rust::Box<DataChannelObserverWrapper> observer)
: observer_(std::move(observer)) {}
rust::Box<DataChannelObserverWrapper> observer,
DataChannel* dc)
: observer_(std::move(observer)), dc_(dc) {}
NativeDataChannelObserver::~NativeDataChannelObserver() {
dc_->unregister_observer();
}
void NativeDataChannelObserver::OnStateChange() {
observer_->on_state_change();
observer_->on_state_change(dc_->state());
}
void NativeDataChannelObserver::OnMessage(const webrtc::DataBuffer& buffer) {
@@ -93,8 +99,9 @@ void NativeDataChannelObserver::OnBufferedAmountChange(
observer_->on_buffered_amount_change(sent_data_size);
}
std::unique_ptr<NativeDataChannelObserver> create_native_data_channel_observer(
rust::Box<DataChannelObserverWrapper> observer) {
return std::make_unique<NativeDataChannelObserver>(std::move(observer));
std::shared_ptr<NativeDataChannelObserver> create_native_data_channel_observer(
rust::Box<DataChannelObserverWrapper> observer,
DataChannel* dc) {
return std::make_shared<NativeDataChannelObserver>(std::move(observer), dc);
}
} // namespace livekit
+16 -24
View File
@@ -1,5 +1,6 @@
use crate::impl_thread_safety;
use std::slice;
use std::sync::Arc;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
@@ -14,9 +15,6 @@ pub mod ffi {
#[derive(Debug)]
pub struct DataChannelInit {
#[allow(deprecated)]
#[deprecated]
pub reliable: bool,
pub ordered: bool,
pub has_max_retransmit_time: bool,
pub max_retransmit_time: i32,
@@ -48,7 +46,7 @@ pub mod ffi {
extern "Rust" {
type DataChannelObserverWrapper;
fn on_state_change(self: &DataChannelObserverWrapper);
fn on_state_change(self: &DataChannelObserverWrapper, state: DataState);
fn on_message(self: &DataChannelObserverWrapper, buffer: DataBuffer);
fn on_buffered_amount_change(self: &DataChannelObserverWrapper, sent_data_size: u64);
}
@@ -61,11 +59,8 @@ pub mod ffi {
type NativeDataChannelObserver;
/// SAFETY
/// The observer must live as the datachannel uses it
unsafe fn register_observer(
self: &DataChannel,
observer: Pin<&mut NativeDataChannelObserver>,
);
/// The observer must live as long as the datachannel uses it
unsafe fn register_observer(self: &DataChannel, observer: *mut NativeDataChannelObserver);
fn unregister_observer(self: &DataChannel);
fn send(self: &DataChannel, data: &DataBuffer) -> bool;
@@ -74,11 +69,12 @@ pub mod ffi {
fn close(self: &DataChannel);
fn create_data_channel_init(init: DataChannelInit) -> UniquePtr<NativeDataChannelInit>;
fn create_native_data_channel_observer(
unsafe fn create_native_data_channel_observer(
observer: Box<DataChannelObserverWrapper>,
) -> UniquePtr<NativeDataChannelObserver>;
dc: *mut DataChannel,
) -> SharedPtr<NativeDataChannelObserver>;
fn _unique_data_channel() -> UniquePtr<DataChannel>; // Ignore
fn _shared_data_channel() -> SharedPtr<DataChannel>; // Ignore
}
}
@@ -87,37 +83,33 @@ impl_thread_safety!(ffi::NativeDataChannelObserver, Send + Sync);
// DataChannelObserver
pub trait DataChannelObserver: Send {
fn on_state_change(&self);
pub trait DataChannelObserver: Send + Sync {
fn on_state_change(&self, state: ffi::DataState);
fn on_message(&self, data: &[u8], is_binary: bool);
fn on_buffered_amount_change(&self, sent_data_size: u64);
}
pub struct DataChannelObserverWrapper {
observer: *mut dyn DataChannelObserver,
observer: Arc<dyn DataChannelObserver>,
}
impl DataChannelObserverWrapper {
/// SAFETY
/// DataChannelObserver must lives as long as DataChannelObserverWrapper does
pub unsafe fn new(observer: *mut dyn DataChannelObserver) -> Self {
pub fn new(observer: Arc<dyn DataChannelObserver>) -> Self {
Self { observer }
}
fn on_state_change(&self) {
unsafe {
(*self.observer).on_state_change();
}
fn on_state_change(&self, state: ffi::DataState) {
self.observer.on_state_change(state);
}
fn on_message(&self, buffer: ffi::DataBuffer) {
unsafe {
let data = slice::from_raw_parts(buffer.ptr, buffer.len);
(*self.observer).on_message(data, buffer.binary);
self.observer.on_message(data, buffer.binary);
}
}
fn on_buffered_amount_change(&self, sent_data_size: u64) {
unsafe { (*self.observer).on_buffered_amount_change(sent_data_size) };
self.observer.on_buffered_amount_change(sent_data_size);
}
}
+4
View File
@@ -77,6 +77,10 @@ SessionDescription::SessionDescription(
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description)
: session_description_(std::move(session_description)) {}
SdpType SessionDescription::sdp_type() const {
return static_cast<SdpType>(session_description_->GetType());
}
rust::String SessionDescription::stringify() const {
std::string str;
session_description_->ToString(&str);
+1 -15
View File
@@ -3,7 +3,6 @@ use cxx::UniquePtr;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::mem::ManuallyDrop;
use std::str::FromStr;
use crate::rtc_error::ffi::RTCError;
@@ -59,6 +58,7 @@ pub mod ffi {
fn candidate(self: &IceCandidate) -> String;
fn stringify(self: &IceCandidate) -> String;
fn sdp_type(self: &SessionDescription) -> SdpType;
fn stringify(self: &SessionDescription) -> String;
fn clone(self: &SessionDescription) -> UniquePtr<SessionDescription>;
@@ -115,20 +115,6 @@ impl ffi::SdpParseError {
}
}
impl FromStr for ffi::SdpType {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"offer" => Ok(ffi::SdpType::Offer),
"pranswer" => Ok(ffi::SdpType::PrAnswer),
"answer" => Ok(ffi::SdpType::Answer),
"rollback" => Ok(ffi::SdpType::Rollback),
_ => Err(()),
}
}
}
// CreateSdpObserver
pub struct CreateSdpObserverWrapper {
+44 -37
View File
@@ -17,11 +17,15 @@
#include "livekit/media_stream.h"
#include <algorithm>
#include <iostream>
#include <memory>
#include "api/media_stream_interface.h"
#include "api/video/video_frame.h"
#include "api/video/video_rotation.h"
#include "rtc_base/logging.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/time_utils.h"
namespace livekit {
@@ -61,32 +65,28 @@ std::shared_ptr<VideoTrack> MediaStream::find_video_track(
media_stream_->FindVideoTrack(track_id.c_str()));
}
bool MediaStream::add_audio_track(
std::shared_ptr<AudioTrack> audio_track) const {
return media_stream_->AddTrack(
rtc::scoped_refptr<webrtc::AudioTrackInterface>(
static_cast<webrtc::AudioTrackInterface*>(audio_track->get().get())));
bool MediaStream::add_track(std::shared_ptr<MediaStreamTrack> track) const {
if (track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
return media_stream_->AddTrack(
rtc::scoped_refptr<webrtc::VideoTrackInterface>(
static_cast<webrtc::VideoTrackInterface*>(track->get().get())));
} else {
return media_stream_->AddTrack(
rtc::scoped_refptr<webrtc::AudioTrackInterface>(
static_cast<webrtc::AudioTrackInterface*>(track->get().get())));
}
}
bool MediaStream::add_video_track(
std::shared_ptr<VideoTrack> video_track) const {
return media_stream_->AddTrack(
rtc::scoped_refptr<webrtc::VideoTrackInterface>(
static_cast<webrtc::VideoTrackInterface*>(video_track->get().get())));
}
bool MediaStream::remove_audio_track(
std::shared_ptr<AudioTrack> audio_track) const {
return media_stream_->RemoveTrack(
rtc::scoped_refptr<webrtc::AudioTrackInterface>(
static_cast<webrtc::AudioTrackInterface*>(audio_track->get().get())));
}
bool MediaStream::remove_video_track(
std::shared_ptr<VideoTrack> video_track) const {
return media_stream_->RemoveTrack(
rtc::scoped_refptr<webrtc::VideoTrackInterface>(
static_cast<webrtc::VideoTrackInterface*>(video_track->get().get())));
bool MediaStream::remove_track(std::shared_ptr<MediaStreamTrack> track) const {
if (track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
return media_stream_->RemoveTrack(
rtc::scoped_refptr<webrtc::VideoTrackInterface>(
static_cast<webrtc::VideoTrackInterface*>(track->get().get())));
} else {
return media_stream_->RemoveTrack(
rtc::scoped_refptr<webrtc::AudioTrackInterface>(
static_cast<webrtc::AudioTrackInterface*>(track->get().get())));
}
}
MediaStreamTrack::MediaStreamTrack(
@@ -177,13 +177,13 @@ void NativeVideoFrameSink::OnConstraintsChanged(
observer_->on_constraints_changed(cst);
}
std::unique_ptr<NativeVideoFrameSink> create_native_video_frame_sink(
std::unique_ptr<NativeVideoFrameSink> new_native_video_frame_sink(
rust::Box<VideoFrameSinkWrapper> observer) {
return std::make_unique<NativeVideoFrameSink>(std::move(observer));
}
NativeVideoTrackSource::NativeVideoTrackSource()
: rtc::AdaptedVideoTrackSource(1) {}
: rtc::AdaptedVideoTrackSource(4) {}
NativeVideoTrackSource::~NativeVideoTrackSource() {}
@@ -197,7 +197,6 @@ absl::optional<bool> NativeVideoTrackSource::needs_denoising() const {
webrtc::MediaSourceInterface::SourceState NativeVideoTrackSource::state()
const {
// TODO(theomonnom): expose source state to Rust
return SourceState::kLive;
}
@@ -212,22 +211,23 @@ bool NativeVideoTrackSource::on_captured_frame(
int64_t aligned_timestamp_us = timestamp_aligner_.TranslateTimestamp(
frame.timestamp_us(), rtc::TimeMicros());
rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer =
frame.video_frame_buffer();
int adapted_width, adapted_height, crop_width, crop_height, crop_x, crop_y;
if (!AdaptFrame(frame.width(), frame.height(), frame.timestamp_us(),
if (!AdaptFrame(buffer->width(), buffer->height(), aligned_timestamp_us,
&adapted_width, &adapted_height, &crop_width, &crop_height,
&crop_x, &crop_y)) {
return false;
}
// TODO(theomonnom): Should this be handled by the users?
rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer =
frame.video_frame_buffer();
if (adapted_width != frame.width() || adapted_height != frame.height()) {
buffer = buffer->CropAndScale(crop_x, crop_y, crop_width, crop_height,
adapted_width, adapted_height);
}
if (apply_rotation() && frame.rotation() != webrtc::kVideoRotation_0) {
webrtc::VideoRotation rotation = frame.rotation();
if (apply_rotation() && rotation != webrtc::kVideoRotation_0) {
// If the buffer is I420, rtc::AdaptedVideoTrackSource will handle the
// rotation for us.
buffer = buffer->ToI420();
@@ -235,7 +235,7 @@ bool NativeVideoTrackSource::on_captured_frame(
OnFrame(webrtc::VideoFrame::Builder()
.set_video_frame_buffer(buffer)
.set_rotation(frame.rotation())
.set_rotation(rotation)
.set_timestamp_us(aligned_timestamp_us)
.build());
@@ -247,8 +247,15 @@ AdaptedVideoTrackSource::AdaptedVideoTrackSource(
: source_(source) {}
bool AdaptedVideoTrackSource::on_captured_frame(
std::unique_ptr<VideoFrame> frame) const {
return source_->on_captured_frame(frame->get());
const std::unique_ptr<VideoFrame>& frame) const {
auto rtc_frame = frame->get();
rtc_frame.set_timestamp_us(rtc::TimeMicros());
// auto buffer = webrtc::I420Buffer::Create(1280, 720);
// webrtc::I420Buffer::SetBlack(buffer.get());
// rtc_frame.set_video_frame_buffer(buffer);
return source_->on_captured_frame(rtc_frame);
}
rtc::scoped_refptr<NativeVideoTrackSource> AdaptedVideoTrackSource::get()
@@ -256,8 +263,8 @@ rtc::scoped_refptr<NativeVideoTrackSource> AdaptedVideoTrackSource::get()
return source_;
}
std::unique_ptr<AdaptedVideoTrackSource> create_adapted_video_track_source() {
return std::make_unique<AdaptedVideoTrackSource>(
std::shared_ptr<AdaptedVideoTrackSource> new_adapted_video_track_source() {
return std::make_shared<AdaptedVideoTrackSource>(
rtc::make_ref_counted<NativeVideoTrackSource>());
}
+13 -9
View File
@@ -52,10 +52,8 @@ pub mod ffi {
fn get_video_tracks(self: &MediaStream) -> Vec<VideoTrackPtr>;
fn find_audio_track(self: &MediaStream, track_id: String) -> SharedPtr<AudioTrack>;
fn find_video_track(self: &MediaStream, track_id: String) -> SharedPtr<VideoTrack>;
fn add_audio_track(self: &MediaStream, audio_track: SharedPtr<AudioTrack>) -> bool;
fn add_video_track(self: &MediaStream, video_track: SharedPtr<VideoTrack>) -> bool;
fn remove_audio_track(self: &MediaStream, audio_track: SharedPtr<AudioTrack>) -> bool;
fn remove_video_track(self: &MediaStream, video_track: SharedPtr<VideoTrack>) -> bool;
fn add_track(self: &MediaStream, audio_track: SharedPtr<MediaStreamTrack>) -> bool;
fn remove_track(self: &MediaStream, audio_track: SharedPtr<MediaStreamTrack>) -> bool;
fn kind(self: &MediaStreamTrack) -> String;
fn id(self: &MediaStreamTrack) -> String;
@@ -71,14 +69,19 @@ pub mod ffi {
fn content_hint(self: &VideoTrack) -> ContentHint;
fn set_content_hint(self: &VideoTrack, hint: ContentHint);
fn create_native_video_frame_sink(
fn new_native_video_frame_sink(
observer: Box<VideoFrameSinkWrapper>,
) -> UniquePtr<NativeVideoFrameSink>;
fn on_captured_frame(self: &AdaptedVideoTrackSource, frame: UniquePtr<VideoFrame>) -> bool;
fn on_captured_frame(self: &AdaptedVideoTrackSource, frame: &UniquePtr<VideoFrame>)
-> bool;
unsafe fn media_to_video(track: *const MediaStreamTrack) -> *const VideoTrack;
unsafe fn media_to_audio(track: *const MediaStreamTrack) -> *const AudioTrack;
fn new_adapted_video_track_source() -> SharedPtr<AdaptedVideoTrackSource>;
fn video_to_media(track: SharedPtr<VideoTrack>) -> SharedPtr<MediaStreamTrack>;
fn audio_to_media(track: SharedPtr<AudioTrack>) -> SharedPtr<MediaStreamTrack>;
fn media_to_video(track: SharedPtr<MediaStreamTrack>) -> SharedPtr<VideoTrack>;
fn media_to_audio(track: SharedPtr<MediaStreamTrack>) -> SharedPtr<AudioTrack>;
fn _shared_media_stream_track() -> SharedPtr<MediaStreamTrack>;
fn _shared_audio_track() -> SharedPtr<AudioTrack>;
@@ -103,8 +106,9 @@ impl_thread_safety!(ffi::MediaStream, Send + Sync);
impl_thread_safety!(ffi::AudioTrack, Send + Sync);
impl_thread_safety!(ffi::VideoTrack, Send + Sync);
impl_thread_safety!(ffi::NativeVideoFrameSink, Send + Sync);
impl_thread_safety!(ffi::AdaptedVideoTrackSource, Send + Sync);
pub trait VideoFrameSink: Send + Sync {
pub trait VideoFrameSink: Send {
fn on_frame(&self, frame: UniquePtr<VideoFrame>);
fn on_discarded_frame(&self);
fn on_constraints_changed(&self, constraints: ffi::VideoTrackSourceConstraints);
+58 -11
View File
@@ -70,7 +70,7 @@ void PeerConnection::set_remote_description(
observer.observer);
}
std::unique_ptr<DataChannel> PeerConnection::create_data_channel(
std::shared_ptr<DataChannel> PeerConnection::create_data_channel(
rust::String label,
std::unique_ptr<NativeDataChannelInit> init) const {
auto result =
@@ -80,7 +80,7 @@ std::unique_ptr<DataChannel> PeerConnection::create_data_channel(
throw std::runtime_error(serialize_error(to_error(result.error())));
}
return std::make_unique<DataChannel>(rtc_runtime_, result.value());
return std::make_shared<DataChannel>(rtc_runtime_, result.value());
}
std::shared_ptr<RtpSender> PeerConnection::add_track(
@@ -106,7 +106,7 @@ std::shared_ptr<RtpTransceiver> PeerConnection::add_transceiver(
RtpTransceiverInit init) const {
auto result = peer_connection_->AddTransceiver(
track->get(), to_native_rtp_transceiver_init(init));
if (result.ok())
if (!result.ok())
throw std::runtime_error(serialize_error(to_error(result.error())));
return std::make_shared<RtpTransceiver>(result.value());
@@ -119,7 +119,7 @@ std::shared_ptr<RtpTransceiver> PeerConnection::add_transceiver_for_media(
static_cast<cricket::MediaType>(media_type),
to_native_rtp_transceiver_init(init));
if (result.ok())
if (!result.ok())
throw std::runtime_error(serialize_error(to_error(result.error())));
return std::make_shared<RtpTransceiver>(result.value());
@@ -158,12 +158,48 @@ void PeerConnection::add_ice_candidate(
[&](const webrtc::RTCError& err) { observer.OnComplete(to_error(err)); });
}
std::unique_ptr<SessionDescription> PeerConnection::current_local_description()
const {
auto local_description = peer_connection_->current_local_description();
if (local_description)
return std::make_unique<SessionDescription>(local_description->Clone());
return nullptr;
}
std::unique_ptr<SessionDescription> PeerConnection::current_remote_description()
const {
auto remote_description = peer_connection_->current_remote_description();
if (remote_description)
return std::make_unique<SessionDescription>(remote_description->Clone());
return nullptr;
}
std::unique_ptr<SessionDescription> PeerConnection::pending_local_description()
const {
auto local_description = peer_connection_->pending_local_description();
if (local_description)
return std::make_unique<SessionDescription>(local_description->Clone());
return nullptr;
}
std::unique_ptr<SessionDescription> PeerConnection::pending_remote_description()
const {
auto remote_description = peer_connection_->pending_remote_description();
if (remote_description)
return std::make_unique<SessionDescription>(remote_description->Clone());
return nullptr;
}
std::unique_ptr<SessionDescription> PeerConnection::local_description() const {
auto local_description = peer_connection_->local_description();
if (local_description)
return std::make_unique<SessionDescription>(local_description->Clone());
return std::unique_ptr<SessionDescription>();
return nullptr;
}
std::unique_ptr<SessionDescription> PeerConnection::remote_description() const {
@@ -171,7 +207,12 @@ std::unique_ptr<SessionDescription> PeerConnection::remote_description() const {
if (remote_description)
return std::make_unique<SessionDescription>(remote_description->Clone());
return std::unique_ptr<SessionDescription>();
return nullptr;
}
PeerConnectionState PeerConnection::connection_state() const {
return static_cast<PeerConnectionState>(
peer_connection_->peer_connection_state());
}
SignalingState PeerConnection::signaling_state() const {
@@ -188,7 +229,7 @@ IceConnectionState PeerConnection::ice_connection_state() const {
peer_connection_->ice_connection_state());
}
void PeerConnection::close() {
void PeerConnection::close() const {
peer_connection_->Close();
}
@@ -213,7 +254,13 @@ create_native_add_ice_candidate_observer(
NativePeerConnectionObserver::NativePeerConnectionObserver(
std::shared_ptr<RTCRuntime> rtc_runtime,
rust::Box<PeerConnectionObserverWrapper> observer)
: rtc_runtime_(std::move(rtc_runtime)), observer_(std::move(observer)) {}
: rtc_runtime_(std::move(rtc_runtime)), observer_(std::move(observer)) {
RTC_LOG(LS_INFO) << "NativePeerConnectionObserver()";
}
NativePeerConnectionObserver::~NativePeerConnectionObserver() {
RTC_LOG(LS_INFO) << "~NativePeerConnectionObserver()";
}
void NativePeerConnectionObserver::OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) {
@@ -233,7 +280,7 @@ void NativePeerConnectionObserver::OnRemoveStream(
void NativePeerConnectionObserver::OnDataChannel(
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
observer_->on_data_channel(
std::make_unique<DataChannel>(rtc_runtime_, data_channel));
std::make_shared<DataChannel>(rtc_runtime_, data_channel));
}
void NativePeerConnectionObserver::OnRenegotiationNeeded() {
@@ -342,11 +389,11 @@ void NativePeerConnectionObserver::OnInterestingUsage(int usage_pattern) {
observer_->on_interesting_usage(usage_pattern);
}
std::unique_ptr<NativePeerConnectionObserver>
std::shared_ptr<NativePeerConnectionObserver>
create_native_peer_connection_observer(
std::shared_ptr<RTCRuntime> rtc_runtime,
rust::Box<PeerConnectionObserverWrapper> observer) {
return std::make_unique<NativePeerConnectionObserver>(rtc_runtime,
return std::make_shared<NativePeerConnectionObserver>(rtc_runtime,
std::move(observer));
}
} // namespace livekit
+36 -71
View File
@@ -6,8 +6,9 @@ use crate::media_stream::ffi::MediaStream;
use crate::rtc_error::ffi::RTCError;
use crate::rtp_receiver::ffi::RtpReceiver;
use crate::rtp_transceiver::ffi::RtpTransceiver;
use cxx::{SharedPtr, UniquePtr};
use cxx::SharedPtr;
use std::mem::ManuallyDrop;
use std::sync::Arc;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
@@ -183,7 +184,7 @@ pub mod ffi {
self: &PeerConnection,
label: String,
init: UniquePtr<NativeDataChannelInit>,
) -> Result<UniquePtr<DataChannel>>;
) -> Result<SharedPtr<DataChannel>>;
fn add_ice_candidate(
self: &PeerConnection,
@@ -191,9 +192,11 @@ pub mod ffi {
observer: Pin<&mut NativeAddIceCandidateObserver>,
);
fn local_description(self: &PeerConnection) -> UniquePtr<SessionDescription>;
fn current_local_description(self: &PeerConnection) -> UniquePtr<SessionDescription>;
fn remote_description(self: &PeerConnection) -> UniquePtr<SessionDescription>;
fn current_remote_description(self: &PeerConnection) -> UniquePtr<SessionDescription>;
fn connection_state(self: &PeerConnection) -> PeerConnectionState;
fn signaling_state(self: &PeerConnection) -> SignalingState;
@@ -201,18 +204,18 @@ pub mod ffi {
fn ice_connection_state(self: &PeerConnection) -> IceConnectionState;
fn close(self: Pin<&mut PeerConnection>);
fn close(self: &PeerConnection);
fn create_native_peer_connection_observer(
rtc_runtime: SharedPtr<RTCRuntime>,
observer: Box<PeerConnectionObserverWrapper>,
) -> UniquePtr<NativePeerConnectionObserver>;
) -> SharedPtr<NativePeerConnectionObserver>;
fn create_native_add_ice_candidate_observer(
observer: Box<AddIceCandidateObserverWrapper>,
) -> UniquePtr<NativeAddIceCandidateObserver>;
fn _unique_peer_connection() -> UniquePtr<PeerConnection>; // Ignore
fn _shared_peer_connection() -> SharedPtr<PeerConnection>; // Ignore
}
extern "Rust" {
@@ -227,7 +230,7 @@ pub mod ffi {
fn on_remove_stream(self: &PeerConnectionObserverWrapper, stream: SharedPtr<MediaStream>);
fn on_data_channel(
self: &PeerConnectionObserverWrapper,
data_channel: UniquePtr<DataChannel>,
data_channel: SharedPtr<DataChannel>,
);
fn on_renegotiation_needed(self: &PeerConnectionObserverWrapper);
fn on_negotiation_needed_event(self: &PeerConnectionObserverWrapper, event: u32);
@@ -325,7 +328,7 @@ pub trait PeerConnectionObserver: Send + Sync {
fn on_signaling_change(&self, new_state: ffi::SignalingState);
fn on_add_stream(&self, stream: SharedPtr<MediaStream>);
fn on_remove_stream(&self, stream: SharedPtr<MediaStream>);
fn on_data_channel(&self, data_channel: UniquePtr<DataChannel>);
fn on_data_channel(&self, data_channel: SharedPtr<DataChannel>);
fn on_renegotiation_needed(&self);
fn on_negotiation_needed_event(&self, event: u32);
fn on_ice_connection_change(&self, new_state: ffi::IceConnectionState);
@@ -352,80 +355,57 @@ pub trait PeerConnectionObserver: Send + Sync {
// Thread safety is handled inside PeerConnectionObserver
pub struct PeerConnectionObserverWrapper {
observer: *mut dyn PeerConnectionObserver,
observer: Arc<dyn PeerConnectionObserver>,
}
impl PeerConnectionObserverWrapper {
/// # Safety
/// PeerConnectionObserver must lives as long as PeerConnectionObserverWrapper does
pub unsafe fn new(observer: *mut dyn PeerConnectionObserver) -> Self {
pub fn new(observer: Arc<dyn PeerConnectionObserver>) -> Self {
Self { observer }
}
fn on_signaling_change(&self, new_state: ffi::SignalingState) {
unsafe {
(*self.observer).on_signaling_change(new_state);
}
self.observer.on_signaling_change(new_state);
}
fn on_add_stream(&self, stream: SharedPtr<MediaStream>) {
unsafe {
(*self.observer).on_add_stream(stream);
}
self.observer.on_add_stream(stream);
}
fn on_remove_stream(&self, stream: SharedPtr<MediaStream>) {
unsafe {
(*self.observer).on_remove_stream(stream);
}
self.observer.on_remove_stream(stream);
}
fn on_data_channel(&self, data_channel: UniquePtr<DataChannel>) {
unsafe {
(*self.observer).on_data_channel(data_channel);
}
fn on_data_channel(&self, data_channel: SharedPtr<DataChannel>) {
self.observer.on_data_channel(data_channel);
}
fn on_renegotiation_needed(&self) {
unsafe {
(*self.observer).on_renegotiation_needed();
}
self.observer.on_renegotiation_needed();
}
fn on_negotiation_needed_event(&self, event: u32) {
unsafe {
(*self.observer).on_negotiation_needed_event(event);
}
self.observer.on_negotiation_needed_event(event);
}
fn on_ice_connection_change(&self, new_state: ffi::IceConnectionState) {
unsafe {
(*self.observer).on_ice_connection_change(new_state);
}
self.observer.on_ice_connection_change(new_state);
}
fn on_standardized_ice_connection_change(&self, new_state: ffi::IceConnectionState) {
unsafe {
(*self.observer).on_standardized_ice_connection_change(new_state);
}
self.observer
.on_standardized_ice_connection_change(new_state);
}
fn on_connection_change(&self, new_state: ffi::PeerConnectionState) {
unsafe {
(*self.observer).on_connection_change(new_state);
}
self.observer.on_connection_change(new_state);
}
fn on_ice_gathering_change(&self, new_state: ffi::IceGatheringState) {
unsafe {
(*self.observer).on_ice_gathering_change(new_state);
}
self.observer.on_ice_gathering_change(new_state);
}
fn on_ice_candidate(&self, candidate: SharedPtr<IceCandidate>) {
unsafe {
(*self.observer).on_ice_candidate(candidate);
}
self.observer.on_ice_candidate(candidate);
}
fn on_ice_candidate_error(
@@ -436,9 +416,8 @@ impl PeerConnectionObserverWrapper {
error_code: i32,
error_text: String,
) {
unsafe {
(*self.observer).on_ice_candidate_error(address, port, url, error_code, error_text);
}
self.observer
.on_ice_candidate_error(address, port, url, error_code, error_text);
}
fn on_ice_candidates_removed(&self, removed: Vec<ffi::CandidatePtr>) {
@@ -448,21 +427,15 @@ impl PeerConnectionObserverWrapper {
vec.push(v.ptr);
}
unsafe {
(*self.observer).on_ice_candidates_removed(vec);
}
self.observer.on_ice_candidates_removed(vec);
}
fn on_ice_connection_receiving_change(&self, receiving: bool) {
unsafe {
(*self.observer).on_ice_connection_receiving_change(receiving);
}
self.observer.on_ice_connection_receiving_change(receiving);
}
fn on_ice_selected_candidate_pair_changed(&self, event: ffi::CandidatePairChangeEvent) {
unsafe {
(*self.observer).on_ice_selected_candidate_pair_changed(event);
}
self.observer.on_ice_selected_candidate_pair_changed(event);
}
fn on_add_track(&self, receiver: SharedPtr<RtpReceiver>, streams: Vec<ffi::MediaStreamPtr>) {
@@ -472,26 +445,18 @@ impl PeerConnectionObserverWrapper {
vec.push(v.ptr);
}
unsafe {
(*self.observer).on_add_track(receiver, vec);
}
self.observer.on_add_track(receiver, vec);
}
fn on_track(&self, transceiver: SharedPtr<RtpTransceiver>) {
unsafe {
(*self.observer).on_track(transceiver);
}
self.observer.on_track(transceiver);
}
fn on_remove_track(&self, receiver: SharedPtr<RtpReceiver>) {
unsafe {
(*self.observer).on_remove_track(receiver);
}
self.observer.on_remove_track(receiver);
}
fn on_interesting_usage(&self, usage_pattern: i32) {
unsafe {
(*self.observer).on_interesting_usage(usage_pattern);
}
self.observer.on_interesting_usage(usage_pattern);
}
}
+27 -6
View File
@@ -20,11 +20,13 @@
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "livekit/rtc_error.h"
#include "livekit/rtp_parameters.h"
#include "livekit/video_decoder_factory.h"
#include "livekit/video_encoder_factory.h"
#include "media/engine/webrtc_media_engine.h"
@@ -73,10 +75,10 @@ PeerConnectionFactory::~PeerConnectionFactory() {
RTC_LOG(LS_INFO) << "PeerConnectionFactory::~PeerConnectionFactory()";
}
std::unique_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(
std::shared_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(
std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config,
NativePeerConnectionObserver& observer) const {
webrtc::PeerConnectionDependencies deps{&observer};
NativePeerConnectionObserver* observer) const {
webrtc::PeerConnectionDependencies deps{observer};
auto result =
peer_factory_->CreatePeerConnectionOrError(*config, std::move(deps));
@@ -84,12 +86,31 @@ std::unique_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(
throw std::runtime_error(serialize_error(to_error(result.error())));
}
return std::make_unique<PeerConnection>(rtc_runtime_, result.value());
return std::make_shared<PeerConnection>(rtc_runtime_, result.value());
}
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory(
std::shared_ptr<VideoTrack> PeerConnectionFactory::create_video_track(
rust::String label,
std::shared_ptr<AdaptedVideoTrackSource> source) const {
return std::make_shared<VideoTrack>(
peer_factory_->CreateVideoTrack(label.c_str(), source->get().get()));
}
RtpCapabilities PeerConnectionFactory::get_rtp_sender_capabilities(
MediaType type) const {
return to_rust_rtp_capabilities(peer_factory_->GetRtpSenderCapabilities(
static_cast<cricket::MediaType>(type)));
}
RtpCapabilities PeerConnectionFactory::get_rtp_receiver_capabilities(
MediaType type) const {
return to_rust_rtp_capabilities(peer_factory_->GetRtpReceiverCapabilities(
static_cast<cricket::MediaType>(type)));
}
std::shared_ptr<PeerConnectionFactory> create_peer_connection_factory(
std::shared_ptr<RTCRuntime> rtc_runtime) {
return std::make_unique<PeerConnectionFactory>(std::move(rtc_runtime));
return std::make_shared<PeerConnectionFactory>(std::move(rtc_runtime));
}
std::unique_ptr<NativeRTCConfiguration> create_rtc_configuration(
+30 -3
View File
@@ -32,6 +32,17 @@ pub mod ffi {
pub ice_transport_type: IceTransportsType,
}
extern "C++" {
include!("livekit/media_stream.h");
include!("livekit/webrtc.h");
include!("livekit/rtp_parameters.h");
type AdaptedVideoTrackSource = crate::media_stream::ffi::AdaptedVideoTrackSource;
type VideoTrack = crate::media_stream::ffi::VideoTrack;
type RtpCapabilities = crate::rtp_parameters::ffi::RtpCapabilities;
type MediaType = crate::webrtc::ffi::MediaType;
}
unsafe extern "C++" {
include!("livekit/peer_connection_factory.h");
@@ -44,7 +55,7 @@ pub mod ffi {
fn create_peer_connection_factory(
runtime: SharedPtr<RTCRuntime>,
) -> UniquePtr<PeerConnectionFactory>;
) -> SharedPtr<PeerConnectionFactory>;
fn create_rtc_configuration(conf: RTCConfiguration) -> UniquePtr<NativeRTCConfiguration>;
/// # Safety
@@ -52,8 +63,24 @@ pub mod ffi {
unsafe fn create_peer_connection(
self: &PeerConnectionFactory,
config: UniquePtr<NativeRTCConfiguration>,
observer: Pin<&mut NativePeerConnectionObserver>,
) -> Result<UniquePtr<PeerConnection>>;
observer: *mut NativePeerConnectionObserver,
) -> Result<SharedPtr<PeerConnection>>;
fn create_video_track(
self: &PeerConnectionFactory,
label: String,
source: SharedPtr<AdaptedVideoTrackSource>,
) -> SharedPtr<VideoTrack>;
fn get_rtp_sender_capabilities(
self: &PeerConnectionFactory,
kind: MediaType,
) -> RtpCapabilities;
fn get_rtp_receiver_capabilities(
self: &PeerConnectionFactory,
kind: MediaType,
) -> RtpCapabilities;
}
}
+24 -26
View File
@@ -19,7 +19,7 @@
namespace livekit {
webrtc::RtcpFeedback to_native_rtcp_feedback(RtcpFeedback feedback) {
webrtc::RtcpFeedback native;
webrtc::RtcpFeedback native{};
native.type = static_cast<webrtc::RtcpFeedbackType>(feedback.feedback_type);
if (feedback.has_message_type)
native.message_type =
@@ -30,14 +30,14 @@ webrtc::RtcpFeedback to_native_rtcp_feedback(RtcpFeedback feedback) {
webrtc::RtpCodecCapability to_native_rtp_codec_capability(
RtpCodecCapability capability) {
webrtc::RtpCodecCapability native;
webrtc::RtpCodecCapability native{};
// native.mime_type(); IGNORED
native.name = capability.name.c_str();
native.kind = static_cast<cricket::MediaType>(capability.kind);
if (capability.has_clock_rate)
native.clock_rate = native.clock_rate;
native.clock_rate = capability.clock_rate;
if (capability.has_preferred_payload_type)
native.preferred_payload_type = capability.preferred_payload_type;
@@ -62,9 +62,7 @@ webrtc::RtpCodecCapability to_native_rtp_codec_capability(
native.max_temporal_layer_extensions =
capability.max_temporal_layer_extensions;
native.max_spatial_layer_extensions = capability.max_spatial_layer_extensions;
native.svc_multi_stream_support = capability.svc_multi_stream_support;
return native;
@@ -72,7 +70,7 @@ webrtc::RtpCodecCapability to_native_rtp_codec_capability(
webrtc::RtpHeaderExtensionCapability to_native_rtp_header_extension_capability(
RtpHeaderExtensionCapability header) {
webrtc::RtpHeaderExtensionCapability native;
webrtc::RtpHeaderExtensionCapability native{};
native.uri = header.uri.c_str();
if (header.has_preferred_id)
@@ -86,7 +84,7 @@ webrtc::RtpHeaderExtensionCapability to_native_rtp_header_extension_capability(
}
webrtc::RtpExtension to_native_rtp_extension(RtpExtension ext) {
webrtc::RtpExtension native;
webrtc::RtpExtension native{};
native.uri = ext.uri.c_str();
native.id = ext.id;
native.encrypt = ext.encrypt;
@@ -94,7 +92,7 @@ webrtc::RtpExtension to_native_rtp_extension(RtpExtension ext) {
}
webrtc::RtpFecParameters to_rtp_fec_parameters(RtpFecParameters fec) {
webrtc::RtpFecParameters native;
webrtc::RtpFecParameters native{};
if (fec.has_ssrc)
native.ssrc = fec.ssrc;
@@ -104,7 +102,7 @@ webrtc::RtpFecParameters to_rtp_fec_parameters(RtpFecParameters fec) {
}
webrtc::RtpRtxParameters to_rtp_rtx_parameters(RtpRtxParameters rtx) {
webrtc::RtpRtxParameters native;
webrtc::RtpRtxParameters native{};
if (rtx.has_ssrc)
native.ssrc = rtx.ssrc;
@@ -113,7 +111,7 @@ webrtc::RtpRtxParameters to_rtp_rtx_parameters(RtpRtxParameters rtx) {
webrtc::RtpEncodingParameters to_native_rtp_encoding_paramters(
RtpEncodingParameters parameters) {
webrtc::RtpEncodingParameters native;
webrtc::RtpEncodingParameters native{};
native.rid = parameters.rid.c_str();
if (parameters.has_ssrc)
@@ -147,7 +145,7 @@ webrtc::RtpEncodingParameters to_native_rtp_encoding_paramters(
webrtc::RtpCodecParameters to_native_rtp_codec_parameters(
RtpCodecParameters params) {
webrtc::RtpCodecParameters native;
webrtc::RtpCodecParameters native{};
native.name = params.name.c_str();
native.kind = static_cast<cricket::MediaType>(params.kind);
native.payload_type = params.payload_type;
@@ -174,7 +172,7 @@ webrtc::RtpCodecParameters to_native_rtp_codec_parameters(
}
webrtc::RtpCapabilities to_rtp_capabilities(RtpCapabilities capabilities) {
webrtc::RtpCapabilities native;
webrtc::RtpCapabilities native{};
for (auto codec : capabilities.codecs)
native.codecs.push_back(to_native_rtp_codec_capability(codec));
@@ -189,7 +187,7 @@ webrtc::RtpCapabilities to_rtp_capabilities(RtpCapabilities capabilities) {
}
webrtc::RtcpParameters to_native_rtcp_paramaters(RtcpParameters params) {
webrtc::RtcpParameters native;
webrtc::RtcpParameters native{};
if (params.has_ssrc)
native.ssrc = params.ssrc;
@@ -200,7 +198,7 @@ webrtc::RtcpParameters to_native_rtcp_paramaters(RtcpParameters params) {
}
webrtc::RtpParameters to_native_rtp_parameters(RtpParameters params) {
webrtc::RtpParameters native;
webrtc::RtpParameters native{};
native.transaction_id = params.transaction_id.c_str();
native.mid = params.mid.c_str();
@@ -223,7 +221,7 @@ webrtc::RtpParameters to_native_rtp_parameters(RtpParameters params) {
}
RtcpFeedback to_rust_rtcp_feedback(webrtc::RtcpFeedback feedback) {
RtcpFeedback rust;
RtcpFeedback rust{};
rust.feedback_type = static_cast<RtcpFeedbackType>(feedback.type);
if (feedback.message_type.has_value()) {
@@ -237,7 +235,7 @@ RtcpFeedback to_rust_rtcp_feedback(webrtc::RtcpFeedback feedback) {
RtpCodecCapability to_rust_rtp_codec_capability(
webrtc::RtpCodecCapability capability) {
RtpCodecCapability rust;
RtpCodecCapability rust{};
rust.mime_type = capability.mime_type();
rust.name = capability.name;
rust.kind = static_cast<MediaType>(capability.kind);
@@ -262,7 +260,7 @@ RtpCodecCapability to_rust_rtp_codec_capability(
rust.ptime = capability.ptime.value();
}
if (capability.num_channels.has_value()) {
if (capability.num_channels) {
rust.has_num_channels = true;
rust.num_channels = capability.num_channels.value();
}
@@ -284,7 +282,7 @@ RtpCodecCapability to_rust_rtp_codec_capability(
RtpHeaderExtensionCapability to_rust_rtp_header_extension_capability(
webrtc::RtpHeaderExtensionCapability header) {
RtpHeaderExtensionCapability rust;
RtpHeaderExtensionCapability rust{};
rust.uri = header.uri;
if (header.preferred_id.has_value()) {
rust.has_preferred_id = true;
@@ -297,7 +295,7 @@ RtpHeaderExtensionCapability to_rust_rtp_header_extension_capability(
}
RtpExtension to_rust_rtp_extension(webrtc::RtpExtension ext) {
RtpExtension rust;
RtpExtension rust{};
rust.uri = ext.uri;
rust.id = ext.id;
rust.encrypt = ext.encrypt;
@@ -305,7 +303,7 @@ RtpExtension to_rust_rtp_extension(webrtc::RtpExtension ext) {
}
RtpFecParameters to_rust_rtp_fec_parameters(webrtc::RtpFecParameters fec) {
RtpFecParameters rust;
RtpFecParameters rust{};
if (fec.ssrc.has_value()) {
rust.has_ssrc = true;
rust.ssrc = fec.ssrc.value();
@@ -316,7 +314,7 @@ RtpFecParameters to_rust_rtp_fec_parameters(webrtc::RtpFecParameters fec) {
}
RtpRtxParameters to_rust_rtp_rtx_parameters(webrtc::RtpRtxParameters param) {
RtpRtxParameters rust;
RtpRtxParameters rust{};
if (param.ssrc.has_value()) {
rust.has_ssrc = param.ssrc.has_value();
rust.ssrc = param.ssrc.value();
@@ -326,7 +324,7 @@ RtpRtxParameters to_rust_rtp_rtx_parameters(webrtc::RtpRtxParameters param) {
RtpEncodingParameters to_rust_rtp_encoding_parameters(
webrtc::RtpEncodingParameters params) {
RtpEncodingParameters rust;
RtpEncodingParameters rust{};
if (params.ssrc.has_value()) {
rust.has_ssrc = params.ssrc.has_value();
rust.ssrc = params.ssrc.value();
@@ -372,7 +370,7 @@ RtpEncodingParameters to_rust_rtp_encoding_parameters(
RtpCodecParameters to_rust_rtp_codec_parameters(
webrtc::RtpCodecParameters params) {
RtpCodecParameters rust;
RtpCodecParameters rust{};
rust.mime_type = params.mime_type();
rust.name = params.name;
rust.kind = static_cast<MediaType>(params.kind);
@@ -407,7 +405,7 @@ RtpCodecParameters to_rust_rtp_codec_parameters(
}
RtpCapabilities to_rust_rtp_capabilities(webrtc::RtpCapabilities capabilities) {
RtpCapabilities rust;
RtpCapabilities rust{};
for (auto codec : capabilities.codecs)
rust.codecs.push_back(to_rust_rtp_codec_capability(codec));
@@ -422,7 +420,7 @@ RtpCapabilities to_rust_rtp_capabilities(webrtc::RtpCapabilities capabilities) {
}
RtcpParameters to_rust_rtcp_parameters(webrtc::RtcpParameters params) {
RtcpParameters rust;
RtcpParameters rust{};
if (params.ssrc.has_value()) {
rust.has_ssrc = true;
rust.ssrc = params.ssrc.value();
@@ -435,7 +433,7 @@ RtcpParameters to_rust_rtcp_parameters(webrtc::RtcpParameters params) {
}
RtpParameters to_rust_rtp_parameters(webrtc::RtpParameters params) {
RtpParameters rust;
RtpParameters rust{};
rust.transaction_id = params.transaction_id;
rust.mid = params.mid;
+15 -17
View File
@@ -1,5 +1,3 @@
use cxx::UniquePtr;
pub const DEFAULT_BITRATE_PRIORITY: f64 = 1.0;
#[cxx::bridge(namespace = "livekit")]
@@ -12,34 +10,34 @@ pub mod ffi {
pub value: String,
}
#[repr(i32)]
#[derive(Debug)]
#[repr(i32)]
pub enum FecMechanism {
RED,
REDAndULPFEC,
FLEXFEC,
Red,
RedAndUlpfec,
FlexFec,
}
#[repr(i32)]
#[derive(Debug)]
#[repr(i32)]
pub enum RtcpFeedbackType {
CCM,
LNTF,
NACK,
REMB,
Ccm,
Lntf,
Nack,
Remb,
TransportCC,
}
#[repr(i32)]
#[derive(Debug)]
#[repr(i32)]
pub enum RtcpFeedbackMessageType {
GenericNACK,
PLI,
FIR,
GenericNack,
Pli,
Fir,
}
#[repr(i32)]
#[derive(Debug)]
#[repr(i32)]
pub enum DegradationPreference {
Disabled,
MaintainFramerate,
@@ -86,8 +84,8 @@ pub mod ffi {
pub direction: RtpTransceiverDirection,
}
#[repr(i32)]
#[derive(Debug)]
#[repr(i32)]
pub enum RtpExtensionFilter {
DiscardEncryptedExtension,
PreferEncryptedExtension,
+4
View File
@@ -1,3 +1,5 @@
use crate::impl_thread_safety;
#[cxx::bridge(namespace = "livekit")]
pub mod ffi {
@@ -31,3 +33,5 @@ pub mod ffi {
fn _shared_rtp_sender() -> SharedPtr<RtpSender>;
}
}
impl_thread_safety!(ffi::RtpSender, Send + Sync);
+2 -1
View File
@@ -21,7 +21,7 @@ namespace livekit {
webrtc::RtpTransceiverInit to_native_rtp_transceiver_init(
RtpTransceiverInit init) {
{
webrtc::RtpTransceiverInit native;
webrtc::RtpTransceiverInit native{};
native.direction =
static_cast<webrtc::RtpTransceiverDirection>(init.direction);
native.stream_ids = std::vector<std::string>(init.stream_ids.begin(),
@@ -95,6 +95,7 @@ void RtpTransceiver::stop_standard() const {
void RtpTransceiver::set_codec_preferences(
rust::Vec<RtpCodecCapability> codecs) const {
std::vector<webrtc::RtpCodecCapability> std_codecs;
for (auto codec : codecs)
std_codecs.push_back(to_native_rtp_codec_capability(codec));
+1
View File
@@ -24,6 +24,7 @@ pub mod ffi {
crate::rtp_parameters::ffi::RtpHeaderExtensionCapability;
type RtpSender = crate::rtp_sender::ffi::RtpSender;
type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
type RTCError = crate::rtc_error::ffi::RTCError;
}
unsafe extern "C++" {
+3 -4
View File
@@ -62,9 +62,8 @@ webrtc::VideoFrame VideoFrame::get() const {
return frame_;
}
void VideoFrameBuilder::set_video_frame_buffer(
std::unique_ptr<VideoFrameBuffer> buffer) {
builder_.set_video_frame_buffer(buffer->get());
void VideoFrameBuilder::set_video_frame_buffer(const VideoFrameBuffer& buffer) {
builder_.set_video_frame_buffer(buffer.get()); // const & ref_counted
}
void VideoFrameBuilder::set_timestamp_us(int64_t timestamp_us) {
@@ -83,7 +82,7 @@ std::unique_ptr<VideoFrame> VideoFrameBuilder::build() {
return std::make_unique<VideoFrame>(builder_.build());
}
std::unique_ptr<VideoFrameBuilder> create_video_frame_builder() {
std::unique_ptr<VideoFrameBuilder> new_video_frame_builder() {
return std::make_unique<VideoFrameBuilder>();
}
+6 -7
View File
@@ -21,7 +21,6 @@ pub mod ffi {
include!("livekit/video_frame.h");
type VideoFrame;
type VideoFrameBuilder;
fn width(self: &VideoFrame) -> i32;
fn height(self: &VideoFrame) -> i32;
@@ -32,18 +31,18 @@ pub mod ffi {
fn transport_frame_id(self: &VideoFrame) -> u32;
fn timestamp(self: &VideoFrame) -> u32;
fn rotation(self: &VideoFrame) -> VideoRotation;
fn video_frame_buffer(self: &VideoFrame) -> UniquePtr<VideoFrameBuffer>;
unsafe fn video_frame_buffer(self: &VideoFrame) -> UniquePtr<VideoFrameBuffer>;
fn set_video_frame_buffer(
self: Pin<&mut VideoFrameBuilder>,
buffer: UniquePtr<VideoFrameBuffer>,
);
// VideoFrameBuilder
type VideoFrameBuilder;
fn new_video_frame_builder() -> UniquePtr<VideoFrameBuilder>;
fn set_timestamp_us(self: Pin<&mut VideoFrameBuilder>, timestamp_us: i64);
fn set_rotation(self: Pin<&mut VideoFrameBuilder>, rotation: VideoRotation);
fn set_id(self: Pin<&mut VideoFrameBuilder>, id: u16);
fn set_video_frame_buffer(self: Pin<&mut VideoFrameBuilder>, buffer: &VideoFrameBuffer);
fn build(self: Pin<&mut VideoFrameBuilder>) -> UniquePtr<VideoFrame>;
fn create_video_frame_builder() -> UniquePtr<VideoFrameBuilder>;
}
}
+19 -2
View File
@@ -34,7 +34,7 @@ int VideoFrameBuffer::height() const {
return buffer_->height();
}
std::unique_ptr<I420Buffer> VideoFrameBuffer::to_i420() {
std::unique_ptr<I420Buffer> VideoFrameBuffer::to_i420() const {
return std::make_unique<I420Buffer>(buffer_->ToI420());
}
@@ -187,11 +187,16 @@ webrtc::BiplanarYuv8Buffer* BiplanarYuv8Buffer::buffer() const {
return static_cast<webrtc::BiplanarYuv8Buffer*>(buffer_.get());
}
std::unique_ptr<I420Buffer> create_i420_buffer(int width, int height) {
std::unique_ptr<I420Buffer> new_i420_buffer(int width, int height) {
return std::make_unique<I420Buffer>(
webrtc::I420Buffer::Create(width, height));
}
std::unique_ptr<I420Buffer> copy_i420_buffer(
const std::unique_ptr<I420Buffer>& i420) {
return std::make_unique<I420Buffer>(webrtc::I420Buffer::Copy(*i420->get()));
}
I420Buffer::I420Buffer(rtc::scoped_refptr<webrtc::I420BufferInterface> buffer)
: PlanarYuv8Buffer(buffer) {}
@@ -199,6 +204,18 @@ I420ABuffer::I420ABuffer(
rtc::scoped_refptr<webrtc::I420ABufferInterface> buffer)
: I420Buffer(buffer) {}
int I420ABuffer::stride_a() const {
return buffer()->StrideA();
}
const uint8_t* I420ABuffer::data_a() const {
return buffer()->DataA();
}
webrtc::I420ABufferInterface* I420ABuffer::buffer() const {
return static_cast<webrtc::I420ABufferInterface*>(buffer_.get());
}
I422Buffer::I422Buffer(rtc::scoped_refptr<webrtc::I422BufferInterface> buffer)
: PlanarYuv8Buffer(buffer) {}
+9 -2
View File
@@ -34,9 +34,12 @@ pub mod ffi {
fn width(self: &VideoFrameBuffer) -> i32;
fn height(self: &VideoFrameBuffer) -> i32;
/// # SAFETY
/// If the buffer type is I420, the buffer must be cloned before
unsafe fn to_i420(self: &VideoFrameBuffer) -> UniquePtr<I420Buffer>;
/// # SAFETY
/// The functions require ownership
unsafe fn to_i420(self: Pin<&mut VideoFrameBuffer>) -> UniquePtr<I420Buffer>;
unsafe fn get_i420(self: Pin<&mut VideoFrameBuffer>) -> UniquePtr<I420Buffer>;
unsafe fn get_i420a(self: Pin<&mut VideoFrameBuffer>) -> UniquePtr<I420ABuffer>;
unsafe fn get_i422(self: Pin<&mut VideoFrameBuffer>) -> UniquePtr<I422Buffer>;
@@ -66,7 +69,11 @@ pub mod ffi {
fn data_y(self: &BiplanarYuv8Buffer) -> *const u8;
fn data_uv(self: &BiplanarYuv8Buffer) -> *const u8;
fn create_i420_buffer(width: i32, height: i32) -> UniquePtr<I420Buffer>;
fn stride_a(self: &I420ABuffer) -> i32;
fn data_a(self: &I420ABuffer) -> *const u8;
fn new_i420_buffer(width: i32, height: i32) -> UniquePtr<I420Buffer>;
fn copy_i420_buffer(i420: &UniquePtr<I420Buffer>) -> UniquePtr<I420Buffer>;
unsafe fn yuv_to_vfb(yuv: *const PlanarYuvBuffer) -> *const VideoFrameBuffer;
unsafe fn biyuv_to_vfb(yuv: *const BiplanarYuvBuffer) -> *const VideoFrameBuffer;
+6
View File
@@ -16,10 +16,12 @@
#include "livekit/webrtc.h"
#include "rtc_base/helpers.h"
#include "rtc_base/logging.h"
namespace livekit {
RTCRuntime::RTCRuntime() {
// rtc::LogMessage::LogToDebug(rtc::LS_INFO);
RTC_LOG(LS_INFO) << "RTCRuntime()";
RTC_CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
@@ -57,6 +59,10 @@ rtc::Thread* RTCRuntime::signaling_thread() const {
return signaling_thread_.get();
}
rust::String create_random_uuid() {
return rtc::CreateRandomUuid();
}
std::shared_ptr<RTCRuntime> create_rtc_runtime() {
return std::make_shared<RTCRuntime>();
}
+2 -1
View File
@@ -33,9 +33,10 @@ pub mod ffi {
unsafe extern "C++" {
include!("livekit/webrtc.h");
type RTCRuntime;
fn create_random_uuid() -> String;
fn create_rtc_runtime() -> SharedPtr<RTCRuntime>;
}
}
+39 -4
View File
@@ -14,7 +14,7 @@ pub mod ffi {
dst_stride_argb: i32,
width: i32,
height: i32,
);
) -> Result<()>;
unsafe fn i420_to_bgra(
src_y: *const u8,
@@ -27,7 +27,7 @@ pub mod ffi {
dst_stride_bgra: i32,
width: i32,
height: i32,
);
) -> Result<()>;
unsafe fn i420_to_abgr(
src_y: *const u8,
@@ -40,7 +40,7 @@ pub mod ffi {
dst_stride_abgr: i32,
width: i32,
height: i32,
);
) -> Result<()>;
unsafe fn i420_to_rgba(
src_y: *const u8,
@@ -53,6 +53,41 @@ pub mod ffi {
dst_stride_rgba: i32,
width: i32,
height: i32,
);
) -> Result<()>;
unsafe fn argb_to_i420(
src_argb: *const u8,
src_stride_argb: i32,
dst_y: *mut u8,
dst_stride_y: i32,
dst_u: *mut u8,
dst_stride_u: i32,
dst_v: *mut u8,
dst_stride_v: i32,
width: i32,
height: i32,
) -> Result<()>;
unsafe fn abgr_to_i420(
src_abgr: *const u8,
src_stride_abgr: i32,
dst_y: *mut u8,
dst_stride_y: i32,
dst_u: *mut u8,
dst_stride_u: i32,
dst_v: *mut u8,
dst_stride_v: i32,
width: i32,
height: i32,
) -> Result<()>;
unsafe fn argb_to_rgb24(
src_argb: *const u8,
src_stride_argb: i32,
dst_rgb24: *mut u8,
dst_stride_rgb24: i32,
width: i32,
height: i32,
) -> Result<()>;
}
}