From 76e1ca91df1199f9b66edbfa43d3f74e90e0411c Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 5 Jul 2022 16:16:08 +0800 Subject: [PATCH 1/3] unify the protobuf message of vp9/h264/h265 Signed-off-by: 21pages --- libs/hbb_common/protos/message.proto | 30 +++----------- libs/scrap/src/common/codec.rs | 39 ++++------------- libs/scrap/src/common/hwcodec.rs | 62 ++++++++++------------------ libs/scrap/src/common/vpxcodec.rs | 12 +++--- src/server/video_service.rs | 6 +-- 5 files changed, 44 insertions(+), 105 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 40da75a5d..1276d880e 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -1,33 +1,13 @@ syntax = "proto3"; package hbb; -message VP9 { +message EncodedVideoFrame { bytes data = 1; bool key = 2; int64 pts = 3; } -message VP9s { repeated VP9 frames = 1; } - -message H264 { - bytes data = 1; - bool key = 2; - int64 pts = 3; -} - -message H264s { - repeated H264 h264s = 1; -} - -message H265 { - bytes data = 1; - bool key = 2; - int64 pts = 3; -} - -message H265s { - repeated H265 h265s = 1; -} +message EncodedVideoFrames { repeated EncodedVideoFrame frames = 1; } message RGB { bool compress = 1; } @@ -39,11 +19,11 @@ message YUV { message VideoFrame { oneof union { - VP9s vp9s = 6; + EncodedVideoFrames vp9s = 6; RGB rgb = 7; YUV yuv = 8; - H264s h264s = 10; - H265s h265s = 11; + EncodedVideoFrames h264s = 10; + EncodedVideoFrames h265s = 11; } int64 timestamp = 9; } diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 2a05c7326..fb5fc7b6f 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -12,15 +12,11 @@ use crate::vpxcodec::*; use hbb_common::{ anyhow::anyhow, log, - message_proto::{test_delay, video_frame, Message, VP9s, VideoCodecState}, + message_proto::{test_delay, video_frame, EncodedVideoFrames, Message, VideoCodecState}, ResultType, }; #[cfg(feature = "hwcodec")] -use hbb_common::{ - config::Config2, - lazy_static, - message_proto::{H264s, H265s}, -}; +use hbb_common::{config::Config2, lazy_static}; #[cfg(feature = "hwcodec")] lazy_static::lazy_static! { @@ -263,7 +259,7 @@ impl Decoder { #[cfg(feature = "hwcodec")] video_frame::Union::h264s(h264s) => { if let Some(decoder) = &mut self.hw.h264 { - Decoder::handle_h264s_video_frame(decoder, h264s, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h264s, rgb, &mut self.i420) } else { Err(anyhow!("don't support h264!")) } @@ -271,7 +267,7 @@ impl Decoder { #[cfg(feature = "hwcodec")] video_frame::Union::h265s(h265s) => { if let Some(decoder) = &mut self.hw.h265 { - Decoder::handle_h265s_video_frame(decoder, h265s, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h265s, rgb, &mut self.i420) } else { Err(anyhow!("don't support h265!")) } @@ -282,7 +278,7 @@ impl Decoder { fn handle_vp9s_video_frame( decoder: &mut VpxDecoder, - vp9s: &VP9s, + vp9s: &EncodedVideoFrames, rgb: &mut Vec, ) -> ResultType { let mut last_frame = Image::new(); @@ -305,14 +301,14 @@ impl Decoder { } #[cfg(feature = "hwcodec")] - fn handle_h264s_video_frame( + fn handle_hw_video_frame( decoder: &mut HwDecoder, - h264s: &H264s, + frames: &EncodedVideoFrames, rgb: &mut Vec, i420: &mut Vec, ) -> ResultType { let mut ret = false; - for h264 in h264s.h264s.iter() { + for h264 in frames.frames.iter() { for image in decoder.decode(&h264.data)? { // TODO: just process the last frame if image.bgra(rgb, i420).is_ok() { @@ -322,25 +318,6 @@ impl Decoder { } return Ok(ret); } - - #[cfg(feature = "hwcodec")] - fn handle_h265s_video_frame( - decoder: &mut HwDecoder, - h265s: &H265s, - rgb: &mut Vec, - i420: &mut Vec, - ) -> ResultType { - let mut ret = false; - for h265 in h265s.h265s.iter() { - for image in decoder.decode(&h265.data)? { - // TODO: just process the last frame - if image.bgra(rgb, i420).is_ok() { - ret = true; - } - } - } - return Ok(ret); - } } #[cfg(feature = "hwcodec")] diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 70d944a33..8fd78e415 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::{test_delay, H264s, H265s, Message, VideoFrame, H264, H265}, + message_proto::{test_delay, EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame}, ResultType, }; use hwcodec::{ @@ -91,47 +91,27 @@ impl EncoderApi for HwEncoder { ) -> ResultType { let mut msg_out = Message::new(); let mut vf = VideoFrame::new(); - match self.format { - DataFormat::H264 => { - let mut h264s = Vec::new(); - for frame in self.encode(frame).with_context(|| "Failed to encode")? { - h264s.push(H264 { - data: frame.data, - pts: frame.pts as _, - ..Default::default() - }); - } - if h264s.len() > 0 { - vf.set_h264s(H264s { - h264s: h264s.into(), - ..Default::default() - }); - msg_out.set_video_frame(vf); - Ok(msg_out) - } else { - Err(anyhow!("no valid frame")) - } - } - DataFormat::H265 => { - let mut h265s = Vec::new(); - for frame in self.encode(frame).with_context(|| "Failed to encode")? { - h265s.push(H265 { - data: frame.data, - pts: frame.pts, - ..Default::default() - }); - } - if h265s.len() > 0 { - vf.set_h265s(H265s { - h265s, - ..Default::default() - }); - msg_out.set_video_frame(vf); - Ok(msg_out) - } else { - Err(anyhow!("no valid frame")) - } + let mut frames = Vec::new(); + for frame in self.encode(frame).with_context(|| "Failed to encode")? { + frames.push(EncodedVideoFrame { + data: frame.data, + pts: frame.pts as _, + ..Default::default() + }); + } + if frames.len() > 0 { + let frames = EncodedVideoFrames { + frames: frames.into(), + ..Default::default() + }; + match self.format { + DataFormat::H264 => vf.set_h264s(frames), + DataFormat::H265 => vf.set_h265s(frames), } + msg_out.set_video_frame(vf); + Ok(msg_out) + } else { + Err(anyhow!("no valid frame")) } } diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index b9b95b93e..c65bc43ab 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -3,7 +3,9 @@ // https://github.com/rust-av/vpx-rs/blob/master/src/decoder.rs use hbb_common::anyhow::{anyhow, Context}; -use hbb_common::message_proto::{test_delay, Message, VP9s, VideoFrame, VP9}; +use hbb_common::message_proto::{ + test_delay, EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame, +}; use hbb_common::ResultType; use crate::codec::EncoderApi; @@ -289,10 +291,10 @@ impl VpxEncoder { } #[inline] - fn create_msg(vp9s: Vec) -> Message { + fn create_msg(vp9s: Vec) -> Message { let mut msg_out = Message::new(); let mut vf = VideoFrame::new(); - vf.set_vp9s(VP9s { + vf.set_vp9s(EncodedVideoFrames { frames: vp9s.into(), ..Default::default() }); @@ -301,8 +303,8 @@ impl VpxEncoder { } #[inline] - fn create_frame(frame: &EncodeFrame) -> VP9 { - VP9 { + fn create_frame(frame: &EncodeFrame) -> EncodedVideoFrame { + EncodedVideoFrame { data: frame.data.to_vec(), key: frame.key, pts: frame.pts, diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 355a43305..5815ab8b3 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -796,10 +796,10 @@ fn check_privacy_mode_changed(sp: &GenericService, privacy_mode_id: i32) -> Resu #[inline] #[cfg(any(target_os = "android", target_os = "ios"))] -fn create_msg(vp9s: Vec) -> Message { +fn create_msg(vp9s: Vec) -> Message { let mut msg_out = Message::new(); let mut vf = VideoFrame::new(); - vf.set_vp9s(VP9s { + vf.set_vp9s(EncodedVideoFrames { frames: vp9s.into(), ..Default::default() }); @@ -845,7 +845,7 @@ pub fn handle_one_frame_encoded( Ok(()) })?; let mut send_conn_ids: HashSet = Default::default(); - let vp9_frame = VP9 { + let vp9_frame = EncodedVideoFrame { data: frame.to_vec(), key: true, pts: ms, From c4b4ef9576450087d2a786136f64e1a09b252a35 Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 5 Jul 2022 16:31:48 +0800 Subject: [PATCH 2/3] score equals 0 if codec unsupported Signed-off-by: 21pages --- libs/hbb_common/protos/message.proto | 6 ++---- libs/scrap/src/common/codec.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 1276d880e..91f05f80c 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -434,10 +434,8 @@ enum ImageQuality { message VideoCodecState { int32 ScoreVpx = 1; - bool H264 = 2; - int32 ScoreH264 = 3; - bool H265 = 4; - int32 ScoreH265 = 5; + int32 ScoreH264 = 2; + int32 ScoreH265 = 3; } message OptionMessage { diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index fb5fc7b6f..b446acf86 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -135,10 +135,12 @@ impl Encoder { let current_encoder_name = HwEncoder::current_name(); if states.len() > 0 { let (best, _) = HwEncoder::best(false, true); - let enabled_h264 = - best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H264); - let enabled_h265 = - best.h265.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H265); + let enabled_h264 = best.h264.is_some() + && states.len() > 0 + && states.iter().all(|(_, s)| s.ScoreH264 > 0); + let enabled_h265 = best.h265.is_some() + && states.len() > 0 + && states.iter().all(|(_, s)| s.ScoreH265 > 0); // score encoder let mut score_vpx = SCORE_VPX; @@ -238,9 +240,7 @@ impl Decoder { { let mut state = MY_DECODER_STATE.lock().unwrap(); state.ScoreVpx = SCORE_VPX; - state.H264 = decoder.hw.h264.is_some(); state.ScoreH264 = decoder.hw.h264.as_ref().map_or(0, |d| d.info.score); - state.H265 = decoder.hw.h265.is_some(); state.ScoreH265 = decoder.hw.h265.as_ref().map_or(0, |d| d.info.score); } From ba034a56af30f0e2aa2b50ea87838161b0b18004 Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 5 Jul 2022 17:33:21 +0800 Subject: [PATCH 3/3] maint hwcodec config file directly Signed-off-by: 21pages --- libs/hbb_common/src/config.rs | 28 +++------------------------- libs/scrap/src/common/hwcodec.rs | 29 ++++++++++++++++------------- src/ipc.rs | 28 +--------------------------- src/main.rs | 17 ++++------------- src/server.rs | 9 +++++++++ 5 files changed, 33 insertions(+), 78 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 2ddfc5d0d..5bedbad29 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -35,7 +35,6 @@ lazy_static::lazy_static! { static ref CONFIG: Arc> = Arc::new(RwLock::new(Config::load())); static ref CONFIG2: Arc> = Arc::new(RwLock::new(Config2::load())); static ref LOCAL_CONFIG: Arc> = Arc::new(RwLock::new(LocalConfig::load())); - static ref HWCODEC_CONFIG: Arc> = Arc::new(RwLock::new(HwCodecConfig::load())); pub static ref ONLINE: Arc>> = Default::default(); pub static ref PROD_RENDEZVOUS_SERVER: Arc> = Default::default(); pub static ref APP_NAME: Arc> = Arc::new(RwLock::new("RustDesk".to_owned())); @@ -887,38 +886,17 @@ impl LanPeers { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct HwCodecConfig { #[serde(default)] - options: HashMap, + pub options: HashMap, } impl HwCodecConfig { - fn load() -> HwCodecConfig { + pub fn load() -> HwCodecConfig { Config::load_::("_hwcodec") } - fn store(&self) { + pub fn store(&self) { Config::store_(self, "_hwcodec"); } - - pub fn get_option(k: &str) -> String { - if let Some(v) = HWCODEC_CONFIG.read().unwrap().options.get(k) { - v.clone() - } else { - "".to_owned() - } - } - - pub fn set_option(k: String, v: String) { - let mut config = HWCODEC_CONFIG.write().unwrap(); - let v2 = if v.is_empty() { None } else { Some(&v) }; - if v2 != config.options.get(&k) { - if v2.is_none() { - config.options.remove(&k); - } else { - config.options.insert(k, v); - } - config.store(); - } - } } #[cfg(test)] diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 8fd78e415..04b65c969 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -17,10 +17,7 @@ use hwcodec::{ Quality::{self, *}, RateContorl::{self, *}, }; -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; +use std::sync::{Arc, Mutex}; lazy_static::lazy_static! { static ref HW_ENCODER_NAME: Arc>> = Default::default(); @@ -161,7 +158,7 @@ impl HwEncoder { }; let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx)); if write { - let _ = set_config(CFG_KEY_ENCODER, &encoders) + set_config(CFG_KEY_ENCODER, &encoders) .map_err(|e| log::error!("{:?}", e)) .ok(); } @@ -313,7 +310,11 @@ impl HwDecoderImage<'_> { } fn get_config(k: &str) -> ResultType { - let v = HwCodecConfig::get_option(k); + let v = HwCodecConfig::load() + .options + .get(k) + .unwrap_or(&"".to_owned()) + .to_owned(); match CodecInfos::deserialize(&v) { Ok(v) => Ok(v), Err(_) => Err(anyhow!("Failed to get config:{}", k)), @@ -323,26 +324,28 @@ fn get_config(k: &str) -> ResultType { fn set_config(k: &str, v: &CodecInfos) -> ResultType<()> { match v.serialize() { Ok(v) => { - HwCodecConfig::set_option(k.to_owned(), v); + let mut config = HwCodecConfig::load(); + config.options.insert(k.to_owned(), v); + config.store(); Ok(()) } Err(_) => Err(anyhow!("Failed to set config:{}", k)), } } -pub fn check_config() -> Option> { +pub fn check_config() { let (encoders, update_encoders) = HwEncoder::best(false, false); let (decoders, update_decoders) = HwDecoder::best(false, false); if update_encoders || update_decoders { if let Ok(encoders) = encoders.serialize() { if let Ok(decoders) = decoders.serialize() { - return Some(HashMap::from([ - (CFG_KEY_ENCODER.to_owned(), encoders), - (CFG_KEY_DECODER.to_owned(), decoders), - ])); + let mut config = HwCodecConfig::load(); + config.options.insert(CFG_KEY_ENCODER.to_owned(), encoders); + config.options.insert(CFG_KEY_DECODER.to_owned(), decoders); + config.store(); + return; } } log::error!("Failed to serialize codec info"); } - None } diff --git a/src/ipc.rs b/src/ipc.rs index f4f9d4b91..24a156eba 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -1,8 +1,6 @@ use crate::rendezvous_mediator::RendezvousMediator; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub use clipboard::ClipbaordFile; -#[cfg(feature = "hwcodec")] -use hbb_common::config::HwCodecConfig; use hbb_common::{ allow_err, bail, bytes, bytes_codec::BytesCodec, @@ -129,8 +127,6 @@ pub enum Data { ClipbaordFile(ClipbaordFile), ClipboardFileEnabled(bool), PrivacyModeState((i32, PrivacyModeState)), - #[cfg(feature = "hwcodec")] - HwCodecConfig(Option>), } #[tokio::main(flavor = "current_thread")] @@ -340,12 +336,7 @@ async fn handle(data: Data, stream: &mut Connection) { .await ); } - #[cfg(feature = "hwcodec")] - Data::HwCodecConfig(Some(config)) => { - for (k, v) in config { - HwCodecConfig::set_option(k, v); - } - } + _ => {} } } @@ -645,20 +636,3 @@ pub async fn set_socks(value: config::Socks5Server) -> ResultType<()> { .await?; Ok(()) } - -#[cfg(feature = "hwcodec")] -#[tokio::main] -pub async fn check_hwcodec_config() { - if let Some(config) = scrap::hwcodec::check_config() { - match connect(1000, "").await { - Ok(mut conn) => { - if conn.send(&Data::HwCodecConfig(Some(config))).await.is_err() { - log::error!("Failed to send hwcodec config by ipc"); - } - } - Err(err) => { - log::info!("Failed to connect ipc: {:?}", err); - } - } - } -} diff --git a/src/main.rs b/src/main.rs index 9158cab32..2e2e4c8ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,15 +70,6 @@ fn main() { } if args.is_empty() { std::thread::spawn(move || start_server(false)); - #[cfg(feature = "hwcodec")] - if let Ok(exe) = std::env::current_exe() { - std::thread::spawn(move || { - std::process::Command::new(exe) - .arg("--check-hwcodec-config") - .status() - .ok() - }); - } } else { #[cfg(windows)] { @@ -117,10 +108,6 @@ fn main() { args.len() > 1, )); return; - } else if args[0] == "--check-hwcodec-config" { - #[cfg(feature = "hwcodec")] - ipc::check_hwcodec_config(); - return; } } if args[0] == "--remove" { @@ -164,6 +151,10 @@ fn main() { ipc::set_password(args[1].to_owned()).unwrap(); } return; + } else if args[0] == "--check-hwcodec-config" { + #[cfg(feature = "hwcodec")] + scrap::hwcodec::check_config(); + return; } } ui::start(&mut args[..]); diff --git a/src/server.rs b/src/server.rs index 9bafa09d1..eb6f90e0b 100644 --- a/src/server.rs +++ b/src/server.rs @@ -320,6 +320,15 @@ pub async fn start_server(is_server: bool) { std::process::exit(-1); } }); + #[cfg(feature = "hwcodec")] + if let Ok(exe) = std::env::current_exe() { + std::thread::spawn(move || { + std::process::Command::new(exe) + .arg("--check-hwcodec-config") + .status() + .ok() + }); + } #[cfg(windows)] crate::platform::windows::bootstrap(); input_service::fix_key_down_timeout_loop();