diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index f6c57b1e4..40da75a5d 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -479,10 +479,18 @@ message OptionMessage { } message TestDelay { + enum CodecFormat { + Unknown = 0; + VP8 = 1; + VP9 = 2; + H264 = 3; + H265 = 4; + } int64 time = 1; bool from_client = 2; uint32 last_delay = 3; uint32 target_bitrate = 4; + CodecFormat codec_format = 5; } message PublicKey { diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1dad08701..6e9d1a8b9 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -12,7 +12,7 @@ use crate::vpxcodec::*; use hbb_common::{ anyhow::anyhow, log, - message_proto::{video_frame, Message, VP9s, VideoCodecState}, + message_proto::{video_frame, Message, VP9s, VideoCodecState, test_delay}, ResultType, }; #[cfg(feature = "hwcodec")] @@ -52,6 +52,8 @@ pub trait EncoderApi { fn use_yuv(&self) -> bool; fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()>; + + fn get_codec_format(&self) -> test_delay::CodecFormat; } pub struct DecoderCfg { diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 945de6335..70d944a33 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -6,7 +6,7 @@ use hbb_common::{ anyhow::{anyhow, Context}, config::HwCodecConfig, lazy_static, log, - message_proto::{H264s, H265s, Message, VideoFrame, H264, H265}, + message_proto::{test_delay, H264s, H265s, Message, VideoFrame, H264, H265}, ResultType, }; use hwcodec::{ @@ -143,6 +143,13 @@ impl EncoderApi for HwEncoder { self.encoder.set_bitrate((bitrate * 1000) as _).ok(); Ok(()) } + + fn get_codec_format(&self) -> test_delay::CodecFormat { + match self.format { + DataFormat::H264 => test_delay::CodecFormat::H264, + DataFormat::H265 => test_delay::CodecFormat::H265, + } + } } impl HwEncoder { diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 2943419e4..a44078eba 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -3,7 +3,7 @@ // https://github.com/rust-av/vpx-rs/blob/master/src/decoder.rs use hbb_common::anyhow::{anyhow, Context}; -use hbb_common::message_proto::{Message, VP9s, VideoFrame, VP9}; +use hbb_common::message_proto::{Message, VP9s, VideoFrame, VP9, test_delay}; use hbb_common::ResultType; use crate::codec::EncoderApi; @@ -27,6 +27,7 @@ impl Default for VpxVideoCodecId { pub struct VpxEncoder { ctx: vpx_codec_ctx_t, + format: VpxVideoCodecId, width: usize, height: usize, } @@ -96,14 +97,17 @@ impl EncoderApi for VpxEncoder { { match cfg { crate::codec::EncoderCfg::VPX(config) => { + let format; let i; if cfg!(feature = "VP8") { i = match config.codec { VpxVideoCodecId::VP8 => call_vpx_ptr!(vpx_codec_vp8_cx()), VpxVideoCodecId::VP9 => call_vpx_ptr!(vpx_codec_vp9_cx()), }; + format = config.codec; } else { i = call_vpx_ptr!(vpx_codec_vp9_cx()); + format = VpxVideoCodecId::VP9; } let mut c = unsafe { std::mem::MaybeUninit::zeroed().assume_init() }; call_vpx!(vpx_codec_enc_config_default(i, &mut c, 0)); @@ -190,6 +194,7 @@ impl EncoderApi for VpxEncoder { Ok(Self { ctx, + format, width: config.width as _, height: config.height as _, }) @@ -228,6 +233,13 @@ impl EncoderApi for VpxEncoder { call_vpx!(vpx_codec_enc_config_set(&mut self.ctx, &new_enc_cfg)); return Ok(()); } + + fn get_codec_format(&self) -> test_delay::CodecFormat { + match self.format { + VpxVideoCodecId::VP8 => test_delay::CodecFormat::VP8, + VpxVideoCodecId::VP9 => test_delay::CodecFormat::VP9 + } + } } impl VpxEncoder { diff --git a/src/server/connection.rs b/src/server/connection.rs index 46c730092..f8bf5d16a 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -380,6 +380,7 @@ impl Connection { time, last_delay:qos.current_delay, target_bitrate:qos.target_bitrate, + codec_format:qos.codec_format.into(), ..Default::default() }); conn.inner.send(msg_out.into()); diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 10ddf3223..9a42c6c31 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -72,11 +72,11 @@ pub struct VideoQoS { height: u32, user_image_quality: u32, current_image_quality: u32, - + enable_abr: bool, + pub codec_format: test_delay::CodecFormat, pub current_delay: u32, pub fps: u8, // abr pub target_bitrate: u32, // abr - updated: bool, state: DelayState, debounce_count: u32, @@ -110,6 +110,8 @@ impl Default for VideoQoS { fps: FPS, user_image_quality: ImageQuality::Balanced.as_percent(), current_image_quality: ImageQuality::Balanced.as_percent(), + enable_abr: false, + codec_format: Default::default(), width: 0, height: 0, current_delay: 0, @@ -145,14 +147,16 @@ impl VideoQoS { self.current_delay = delay / 2 + self.current_delay / 2; log::trace!( - "VideoQoS update_network_delay:{}, {}, state:{:?},count:{}", + "VideoQoS update_network_delay:{}, {}, state:{:?}", self.current_delay, delay, self.state, - self.debounce_count ); // ABR + if !self.enable_abr { + return; + } let current_state = DelayState::from_delay(self.current_delay); if current_state != self.state && self.debounce_count > 5 { log::debug!( @@ -544,7 +548,6 @@ fn run(sp: GenericService) -> ResultType<()> { video_qos.set_size(width as _, height as _); let mut spf = video_qos.spf(); let bitrate = video_qos.generate_bitrate()?; - drop(video_qos); log::info!("init bitrate={}", bitrate); @@ -571,6 +574,9 @@ fn run(sp: GenericService) -> ResultType<()> { Err(err) => bail!("Failed to create encoder: {}", err), } + video_qos.codec_format = encoder.get_codec_format(); + drop(video_qos); + let privacy_mode_id = *PRIVACY_MODE_CONN_ID.lock().unwrap(); #[cfg(not(windows))] let captuerer_privacy_mode_id = privacy_mode_id; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 22ae5f505..fefc42f98 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -240,6 +240,7 @@ struct QualityStatus { fps: i32, delay: i32, target_bitrate: i32, + codec_format: test_delay::CodecFormat, } impl Default for QualityStatus { @@ -249,6 +250,7 @@ impl Default for QualityStatus { fps: -1, delay: -1, target_bitrate: -1, + codec_format: test_delay::CodecFormat::Unknown, } } } @@ -269,13 +271,21 @@ impl Handler { } fn update_quality_status(&self, status: QualityStatus) { + let codec_format = match status.codec_format { + test_delay::CodecFormat::Unknown => "Unknown", + test_delay::CodecFormat::VP8 => "VP8", + test_delay::CodecFormat::VP9 => "VP9", + test_delay::CodecFormat::H264 => "H264", + test_delay::CodecFormat::H265 => "H265", + }; self.call2( "updateQualityStatus", &make_args!( status.speed, status.fps, status.delay, - status.target_bitrate + status.target_bitrate, + codec_format ), ); } @@ -2604,6 +2614,7 @@ impl Interface for Handler { self.update_quality_status(QualityStatus { delay: t.last_delay as _, target_bitrate: t.target_bitrate as _, + codec_format: t.codec_format.enum_value_or_default(), ..Default::default() }); let mut msg_out = Message::new(); diff --git a/src/ui/remote.tis b/src/ui/remote.tis index cc5727755..dc2470ac1 100644 --- a/src/ui/remote.tis +++ b/src/ui/remote.tis @@ -482,16 +482,20 @@ class QualityMonitor: Reactor.Component <div> Target Bitrate: {qualityMonitorData[3]}kb </div> + <div> + Codec: {qualityMonitorData[4]} + </div> </div>; } } $(#quality-monitor).content(<QualityMonitor />); -handler.updateQualityStatus = function(speed, fps, delay, bitrate) { +handler.updateQualityStatus = function(speed, fps, delay, bitrate, codec_format) { speed ? qualityMonitorData[0] = speed:null; fps > -1 ? qualityMonitorData[1] = fps:null; delay > -1 ? qualityMonitorData[2] = delay:null; bitrate > -1 ? qualityMonitorData[3] = bitrate:null; + codec_format != "Unknown" ? qualityMonitorData[4] = codec_format:null; qualityMonitor.update(); }