diff --git a/examples/wgpu_room/src/app.rs b/examples/wgpu_room/src/app.rs index cbcfdca65..307001cdd 100644 --- a/examples/wgpu_room/src/app.rs +++ b/examples/wgpu_room/src/app.rs @@ -5,9 +5,20 @@ use crate::{ video_renderer::VideoRenderer, }; use egui::{emath, epaint, pos2, Color32, CornerRadius, Rect, Stroke}; -use livekit::{e2ee::EncryptionType, prelude::*, track::VideoQuality, SimulateScenario}; +use livekit::{ + e2ee::EncryptionType, options::VideoCodec, prelude::*, track::VideoQuality, SimulateScenario, +}; use std::collections::HashMap; +#[derive(PartialEq, serde::Deserialize, serde::Serialize)] +enum VideoCodecEnum { + VP8, + VP9, + H264, + H265, + AV1, +} + /// The state of the application are saved on app exit and restored on app start. #[derive(serde::Deserialize, serde::Serialize)] #[serde(default)] @@ -17,6 +28,8 @@ struct AppState { key: String, auto_subscribe: bool, enable_e2ee: bool, + simulcast: bool, + video_codec: VideoCodecEnum, } pub struct LkApp { @@ -39,6 +52,8 @@ impl Default for AppState { auto_subscribe: true, enable_e2ee: false, key: "".to_string(), + simulcast: false, + video_codec: VideoCodecEnum::VP8, } } } @@ -148,7 +163,16 @@ impl LkApp { ui.menu_button("Publish", |ui| { if ui.button("Logo").clicked() { - let _ = self.service.send(AsyncCmd::ToggleLogo); + let _ = self.service.send(AsyncCmd::ToggleLogo { + simulcast: self.state.simulcast, + video_codec: match self.state.video_codec { + VideoCodecEnum::VP8 => VideoCodec::VP8, + VideoCodecEnum::VP9 => VideoCodec::VP9, + VideoCodecEnum::H264 => VideoCodec::H264, + VideoCodecEnum::H265 => VideoCodec::H265, + VideoCodecEnum::AV1 => VideoCodec::AV1, + }, + }); } if ui.button("SineWave").clicked() { let _ = self.service.send(AsyncCmd::ToggleSine); @@ -197,6 +221,23 @@ impl LkApp { }); }); + ui.horizontal(|ui| { + ui.add_enabled_ui(true, |ui| { + ui.checkbox(&mut self.state.simulcast, "Enable Simulcast"); + }); + }); + + ui.horizontal(|ui| { + ui.add_enabled_ui(true, |ui| { + ui.label("Video Codec: "); + ui.radio_value(&mut self.state.video_codec, VideoCodecEnum::VP8, "VP8"); + ui.radio_value(&mut self.state.video_codec, VideoCodecEnum::VP9, "VP9"); + ui.radio_value(&mut self.state.video_codec, VideoCodecEnum::AV1, "AV1"); + ui.radio_value(&mut self.state.video_codec, VideoCodecEnum::H264, "H264"); + ui.radio_value(&mut self.state.video_codec, VideoCodecEnum::H265, "H265"); + }); + }); + ui.horizontal(|ui| { ui.add_enabled_ui(!connected && !self.connecting, |ui| { if ui.button("Connect").clicked() { @@ -309,6 +350,9 @@ impl LkApp { } }); + let codec = publication.mime_type(); + ui.label(format!("Codec: {:?}", codec)); + ui.horizontal(|ui| { if publication.is_muted() { ui.colored_label(egui::Color32::DARK_GRAY, "Muted"); @@ -319,7 +363,6 @@ impl LkApp { } else { ui.colored_label(egui::Color32::RED, "Unsubscribed"); } - if publication.is_subscribed() { if ui.button("Unsubscribe").clicked() { let _ = diff --git a/examples/wgpu_room/src/logo_track.rs b/examples/wgpu_room/src/logo_track.rs index a7d46dee0..0e5e1c2aa 100644 --- a/examples/wgpu_room/src/logo_track.rs +++ b/examples/wgpu_room/src/logo_track.rs @@ -60,7 +60,11 @@ impl LogoTrack { self.handle.is_some() } - pub async fn publish(&mut self) -> Result<(), RoomError> { + pub async fn publish( + &mut self, + simulcast: bool, + video_codec: VideoCodec, + ) -> Result<(), RoomError> { self.unpublish().await?; let (close_tx, close_rx) = oneshot::channel(); @@ -77,8 +81,8 @@ impl LogoTrack { LocalTrack::Video(track.clone()), TrackPublishOptions { source: TrackSource::Camera, - simulcast: true, - video_codec: VideoCodec::H265, + simulcast: simulcast, + video_codec: video_codec, ..Default::default() }, ) diff --git a/examples/wgpu_room/src/service.rs b/examples/wgpu_room/src/service.rs index 04ee939f3..f9c4bca1a 100644 --- a/examples/wgpu_room/src/service.rs +++ b/examples/wgpu_room/src/service.rs @@ -4,6 +4,7 @@ use crate::{ }; use livekit::{ e2ee::{key_provider::*, E2eeOptions, EncryptionType}, + options::VideoCodec, prelude::*, track::VideoQuality, SimulateScenario, @@ -17,7 +18,7 @@ pub enum AsyncCmd { RoomConnect { url: String, token: String, auto_subscribe: bool, enable_e2ee: bool, key: String }, RoomDisconnect, SimulateScenario { scenario: SimulateScenario }, - ToggleLogo, + ToggleLogo { simulcast: bool, video_codec: VideoCodec }, ToggleSine, ToggleDataTrack, SubscribeTrack { publication: RemoteTrackPublication }, @@ -142,12 +143,12 @@ async fn service_task(inner: Arc, mut cmd_rx: mpsc::UnboundedRecei } } } - AsyncCmd::ToggleLogo => { + AsyncCmd::ToggleLogo { simulcast, video_codec } => { if let Some(state) = running_state.as_mut() { if state.logo_track.is_published() { state.logo_track.unpublish().await.unwrap(); } else { - state.logo_track.publish().await.unwrap(); + state.logo_track.publish(simulcast, video_codec).await.unwrap(); } } } diff --git a/livekit/tests/video_test.rs b/livekit/tests/video_test.rs index f6d5f3d3f..05e48d83c 100644 --- a/livekit/tests/video_test.rs +++ b/livekit/tests/video_test.rs @@ -44,6 +44,8 @@ async fn test_video() -> Result<()> { VideoTestParams { codec: VideoCodec::VP8, width: 1280, height: 720, simulcast: true }, VideoTestParams { codec: VideoCodec::VP9, width: 1280, height: 720, simulcast: false }, VideoTestParams { codec: VideoCodec::VP9, width: 1280, height: 720, simulcast: true }, + VideoTestParams { codec: VideoCodec::H264, width: 1280, height: 720, simulcast: false }, + VideoTestParams { codec: VideoCodec::H264, width: 1280, height: 720, simulcast: true }, ]; for params in test_params { log::info!("Testing with {}", params);