Skip to content

Commit eef7d59

Browse files
committed
Set is_screencast on NativeVideoSource creation
Makes InternalSource's is_screencast configurable when creating a NativeVideoSource. This improves the stream's latency when vp9 is used for sharing screen content.
1 parent e96fdca commit eef7d59

File tree

9 files changed

+63
-54
lines changed

9 files changed

+63
-54
lines changed

examples/wgpu_room/src/logo_track.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ pub struct LogoTrack {
4747
impl LogoTrack {
4848
pub fn new(room: Arc<Room>) -> Self {
4949
Self {
50-
rtc_source: NativeVideoSource::new(VideoResolution {
51-
width: FB_WIDTH as u32,
52-
height: FB_HEIGHT as u32,
53-
}),
50+
rtc_source: NativeVideoSource::new(
51+
VideoResolution { width: FB_WIDTH as u32, height: FB_HEIGHT as u32 },
52+
false,
53+
),
5454
room,
5555
handle: None,
5656
}
@@ -83,11 +83,7 @@ impl LogoTrack {
8383
)
8484
.await?;
8585

86-
let handle = TrackHandle {
87-
close_tx,
88-
task,
89-
track,
90-
};
86+
let handle = TrackHandle { close_tx, task, track };
9187

9288
self.handle = Some(handle);
9389
Ok(())
@@ -98,10 +94,7 @@ impl LogoTrack {
9894
let _ = handle.close_tx.send(());
9995
let _ = handle.task.await;
10096

101-
self.room
102-
.local_participant()
103-
.unpublish_track(&handle.track.sid())
104-
.await?;
97+
self.room.local_participant().unpublish_track(&handle.track.sid()).await?;
10598
}
10699
Ok(())
107100
}

libwebrtc/src/native/video_source.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2023 LiveKit, Inc.
1+
// Copyright 2023-2025 LiveKit, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -50,11 +50,12 @@ struct VideoSourceInner {
5050
}
5151

5252
impl NativeVideoSource {
53-
pub fn new(resolution: VideoResolution) -> NativeVideoSource {
53+
pub fn new(resolution: VideoResolution, is_screencast: bool) -> NativeVideoSource {
5454
let source = Self {
55-
sys_handle: vt_sys::ffi::new_video_track_source(&vt_sys::ffi::VideoResolution::from(
56-
resolution.clone(),
57-
)),
55+
sys_handle: vt_sys::ffi::new_video_track_source(
56+
&vt_sys::ffi::VideoResolution::from(resolution.clone()),
57+
is_screencast,
58+
),
5859
inner: Arc::new(Mutex::new(VideoSourceInner { captured_frames: 0 })),
5960
};
6061

libwebrtc/src/video_source.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 LiveKit, Inc.
1+
// Copyright 2024-2025 LiveKit, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -58,13 +58,13 @@ pub mod native {
5858

5959
impl Default for NativeVideoSource {
6060
fn default() -> Self {
61-
Self::new(VideoResolution::default())
61+
Self::new(VideoResolution::default(), false)
6262
}
6363
}
6464

6565
impl NativeVideoSource {
66-
pub fn new(resolution: VideoResolution) -> Self {
67-
Self { handle: vs_imp::NativeVideoSource::new(resolution) }
66+
pub fn new(resolution: VideoResolution, is_screencast: bool) -> Self {
67+
Self { handle: vs_imp::NativeVideoSource::new(resolution, is_screencast) }
6868
}
6969

7070
pub fn capture_frame<T: AsRef<dyn VideoBuffer>>(&self, frame: &VideoFrame<T>) {

livekit-ffi/protocol/video_frame.proto

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2023 LiveKit, Inc.
1+
// Copyright 2023-2025 LiveKit, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -44,11 +44,12 @@ message VideoStreamFromParticipantResponse { required OwnedVideoStream stream =
4444

4545
// Create a new VideoSource
4646
// VideoSource is used to send video frame to a track
47-
message NewVideoSourceRequest {
48-
required VideoSourceType type = 1;
47+
message NewVideoSourceRequest {
48+
required VideoSourceType type = 1;
4949
// Used to determine which encodings to use + simulcast layers
50-
// Most of the time it corresponds to the source resolution
50+
// Most of the time it corresponds to the source resolution
5151
required VideoSourceResolution resolution = 2;
52+
optional bool is_screencast = 3;
5253
}
5354
message NewVideoSourceResponse { required OwnedVideoSource source = 1; }
5455

@@ -70,7 +71,7 @@ message VideoConvertRequest {
7071
message VideoConvertResponse {
7172
oneof message {
7273
string error = 1;
73-
OwnedVideoBuffer buffer = 2;
74+
OwnedVideoBuffer buffer = 2;
7475
}
7576
}
7677

@@ -154,7 +155,7 @@ message OwnedVideoStream {
154155

155156
message VideoStreamEvent {
156157
required uint64 stream_handle = 1;
157-
oneof message {
158+
oneof message {
158159
VideoFrameReceived frame_received = 2;
159160
VideoStreamEOS eos = 3;
160161
}

livekit-ffi/src/livekit.proto.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,11 @@ impl EncryptionState {
302302
/// # Safety
303303
/// The foreign language is responsable for disposing handles
304304
/// Forgetting to dispose the handle may lead to memory leaks
305-
///
305+
///
306306
/// Dropping a handle doesn't necessarily mean that the object is destroyed if it is still used
307307
/// on the FfiServer (Atomic reference counting)
308-
///
309-
/// When refering to a handle without owning it, we just use a uint32 without this message.
308+
///
309+
/// When refering to a handle without owning it, we just use a uint32 without this message.
310310
/// (the variable name is suffixed with "_handle")
311311
#[allow(clippy::derive_partial_eq_without_eq)]
312312
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -1762,9 +1762,11 @@ pub struct NewVideoSourceRequest {
17621762
#[prost(enumeration="VideoSourceType", required, tag="1")]
17631763
pub r#type: i32,
17641764
/// Used to determine which encodings to use + simulcast layers
1765-
/// Most of the time it corresponds to the source resolution
1765+
/// Most of the time it corresponds to the source resolution
17661766
#[prost(message, required, tag="2")]
17671767
pub resolution: VideoSourceResolution,
1768+
#[prost(bool, optional, tag="3")]
1769+
pub is_screencast: ::core::option::Option<bool>,
17681770
}
17691771
#[allow(clippy::derive_partial_eq_without_eq)]
17701772
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -2007,6 +2009,8 @@ impl VideoRotation {
20072009
}
20082010
}
20092011
}
2012+
/// Values of this enum must not be changed
2013+
/// It is used to serialize a rtc.VideoFrame on Python
20102014
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
20112015
#[repr(i32)]
20122016
pub enum VideoBufferType {
@@ -3451,7 +3455,7 @@ pub struct NewAudioSourceResponse {
34513455
#[prost(message, required, tag="1")]
34523456
pub source: OwnedAudioSource,
34533457
}
3454-
/// Push a frame to an AudioSource
3458+
/// Push a frame to an AudioSource
34553459
/// The data provided must be available as long as the client receive the callback.
34563460
#[allow(clippy::derive_partial_eq_without_eq)]
34573461
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -4005,7 +4009,7 @@ pub struct RpcMethodInvocationEvent {
40054009
// that it receives from the server.
40064010
//
40074011
// Therefore, the ffi client is easier to implement if there is less handles to manage.
4008-
//
4012+
//
40094013
// - We are mainly using FfiHandle on info messages (e.g: RoomInfo, TrackInfo, etc...)
40104014
// For this reason, info are only sent once, at creation (We're not using them for updates, we can infer them from
40114015
// events on the client implementation).

livekit-ffi/src/server/video_source.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2023 LiveKit, Inc.
1+
// Copyright 2023-2025 LiveKit, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -35,8 +35,10 @@ impl FfiVideoSource {
3535
#[cfg(not(target_arch = "wasm32"))]
3636
proto::VideoSourceType::VideoSourceNative => {
3737
use livekit::webrtc::video_source::native::NativeVideoSource;
38-
39-
let video_source = NativeVideoSource::new(new_source.resolution.into());
38+
let video_source = NativeVideoSource::new(
39+
new_source.resolution.into(),
40+
new_source.is_screencast(),
41+
);
4042
RtcVideoSource::Native(video_source)
4143
}
4244
_ => return Err(FfiError::InvalidRequest("unsupported video source type".into())),

webrtc-sys/include/livekit/video_track.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 LiveKit
2+
* Copyright 2023-2025 LiveKit
33
*
44
* Licensed under the Apache License, Version 2.0 (the “License”);
55
* you may not use this file except in compliance with the License.
@@ -87,10 +87,11 @@ std::shared_ptr<NativeVideoSink> new_native_video_sink(
8787
class VideoTrackSource {
8888
class InternalSource : public rtc::AdaptedVideoTrackSource {
8989
public:
90-
InternalSource(const VideoResolution&
91-
resolution); // (0, 0) means no resolution/optional, the
92-
// source will guess the resolution at the
93-
// first captured frame
90+
/*
91+
* resolution set to (0, 0) means no resolution/optional, the source will
92+
* guess the resolution at the first captured frame.
93+
*/
94+
InternalSource(const VideoResolution& resolution, bool is_screencast);
9495
~InternalSource() override;
9596

9697
bool is_screencast() const override;
@@ -104,10 +105,11 @@ class VideoTrackSource {
104105
mutable webrtc::Mutex mutex_;
105106
rtc::TimestampAligner timestamp_aligner_;
106107
VideoResolution resolution_;
108+
bool is_screencast_;
107109
};
108110

109111
public:
110-
VideoTrackSource(const VideoResolution& resolution);
112+
VideoTrackSource(const VideoResolution& resolution, bool is_screencast);
111113

112114
VideoResolution video_resolution() const;
113115

@@ -121,7 +123,8 @@ class VideoTrackSource {
121123
};
122124

123125
std::shared_ptr<VideoTrackSource> new_video_track_source(
124-
const VideoResolution& resolution);
126+
const VideoResolution& resolution,
127+
bool is_screencast);
125128

126129
static std::shared_ptr<MediaStreamTrack> video_to_media(
127130
std::shared_ptr<VideoTrack> track) {

webrtc-sys/src/video_track.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 LiveKit
2+
* Copyright 2023-2025 LiveKit
33
*
44
* Licensed under the Apache License, Version 2.0 (the “License”);
55
* you may not use this file except in compliance with the License.
@@ -105,13 +105,16 @@ std::shared_ptr<NativeVideoSink> new_native_video_sink(
105105
}
106106

107107
VideoTrackSource::InternalSource::InternalSource(
108-
const VideoResolution& resolution)
109-
: rtc::AdaptedVideoTrackSource(4), resolution_(resolution) {}
108+
const VideoResolution& resolution,
109+
bool is_screencast)
110+
: rtc::AdaptedVideoTrackSource(4),
111+
resolution_(resolution),
112+
is_screencast_(is_screencast) {}
110113

111114
VideoTrackSource::InternalSource::~InternalSource() {}
112115

113116
bool VideoTrackSource::InternalSource::is_screencast() const {
114-
return false;
117+
return is_screencast_;
115118
}
116119

117120
absl::optional<bool> VideoTrackSource::InternalSource::needs_denoising() const {
@@ -175,8 +178,9 @@ bool VideoTrackSource::InternalSource::on_captured_frame(
175178
return true;
176179
}
177180

178-
VideoTrackSource::VideoTrackSource(const VideoResolution& resolution) {
179-
source_ = rtc::make_ref_counted<InternalSource>(resolution);
181+
VideoTrackSource::VideoTrackSource(const VideoResolution& resolution,
182+
bool is_screencast) {
183+
source_ = rtc::make_ref_counted<InternalSource>(resolution, is_screencast);
180184
}
181185

182186
VideoResolution VideoTrackSource::video_resolution() const {
@@ -195,8 +199,9 @@ rtc::scoped_refptr<VideoTrackSource::InternalSource> VideoTrackSource::get()
195199
}
196200

197201
std::shared_ptr<VideoTrackSource> new_video_track_source(
198-
const VideoResolution& resolution) {
199-
return std::make_shared<VideoTrackSource>(resolution);
202+
const VideoResolution& resolution,
203+
bool is_screencast) {
204+
return std::make_shared<VideoTrackSource>(resolution, is_screencast);
200205
}
201206

202207
} // namespace livekit

webrtc-sys/src/video_track.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2023 LiveKit, Inc.
1+
// Copyright 2023-2025 LiveKit, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@ pub mod ffi {
6767

6868
fn video_resolution(self: &VideoTrackSource) -> VideoResolution;
6969
fn on_captured_frame(self: &VideoTrackSource, frame: &UniquePtr<VideoFrame>) -> bool;
70-
fn new_video_track_source(resolution: &VideoResolution) -> SharedPtr<VideoTrackSource>;
70+
fn new_video_track_source(resolution: &VideoResolution, is_screencast: bool) -> SharedPtr<VideoTrackSource>;
7171
fn video_to_media(track: SharedPtr<VideoTrack>) -> SharedPtr<MediaStreamTrack>;
7272
unsafe fn media_to_video(track: SharedPtr<MediaStreamTrack>) -> SharedPtr<VideoTrack>;
7373
fn _shared_video_track() -> SharedPtr<VideoTrack>;

0 commit comments

Comments
 (0)