From 1b1f28b872a32ba7220affe977d285fae35e57f4 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 8 Jul 2022 18:18:58 +0800 Subject: [PATCH] hwcodec: check when server or each client starts and refactor hwcodec::best() Signed-off-by: 21pages --- libs/hbb_common/src/config.rs | 4 + libs/scrap/src/common/codec.rs | 4 +- libs/scrap/src/common/hwcodec.rs | 127 +++++++++++++------------------ src/server.rs | 17 ++--- 4 files changed, 69 insertions(+), 83 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 787ffe5ee..cf657c8dc 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -978,6 +978,10 @@ impl HwCodecConfig { pub fn store(&self) { Config::store_(self, "_hwcodec"); } + + pub fn remove() { + std::fs::remove_file(Config::file_("_hwcodec")).ok(); + } } #[cfg(test)] diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1d9deba68..b48053e0b 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -102,7 +102,7 @@ impl Encoder { codec: Box::new(hw), }), Err(e) => { - HwEncoder::best(true, true); + check_config_process(true); Err(e) } }, @@ -132,7 +132,7 @@ impl Encoder { } let current_encoder_name = HwEncoder::current_name(); if states.len() > 0 { - let (best, _) = HwEncoder::best(false, true); + let best = HwEncoder::best(); let enabled_h264 = best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.ScoreH264 > 0); diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index ff23978de..c2c853956 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -123,40 +123,11 @@ impl EncoderApi for HwEncoder { } impl HwEncoder { - /// Get best encoders. - /// - /// # Parameter - /// `force_reset`: force to refresh config. - /// `write`: write to config file. - /// - /// # Return - /// `CodecInfos`: infos. - /// `bool`: whether the config is refreshed. - pub fn best(force_reset: bool, write: bool) -> (CodecInfos, bool) { - let config = get_config(CFG_KEY_ENCODER); - if !force_reset && config.is_ok() { - (config.unwrap(), false) - } else { - let ctx = EncodeContext { - name: String::from(""), - width: 1920, - height: 1080, - pixfmt: DEFAULT_PIXFMT, - align: HW_STRIDE_ALIGN as _, - bitrate: 0, - timebase: DEFAULT_TIME_BASE, - gop: DEFAULT_GOP, - quality: DEFAULT_HW_QUALITY, - rc: DEFAULT_RC, - }; - let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx)); - if write { - set_config(CFG_KEY_ENCODER, &encoders) - .map_err(|e| log::error!("{:?}", e)) - .ok(); - } - (encoders, true) - } + pub fn best() -> CodecInfos { + get_config(CFG_KEY_ENCODER).unwrap_or(CodecInfos { + h264: None, + h265: None, + }) } pub fn current_name() -> Arc>> { @@ -207,24 +178,15 @@ pub struct HwDecoders { } impl HwDecoder { - /// See HwEncoder::best - fn best(force_reset: bool, write: bool) -> (CodecInfos, bool) { - let config = get_config(CFG_KEY_DECODER); - if !force_reset && config.is_ok() { - (config.unwrap(), false) - } else { - let decoders = CodecInfo::score(Decoder::avaliable_decoders()); - if write { - set_config(CFG_KEY_DECODER, &decoders) - .map_err(|e| log::error!("{:?}", e)) - .ok(); - } - (decoders, true) - } + fn best() -> CodecInfos { + get_config(CFG_KEY_DECODER).unwrap_or(CodecInfos { + h264: None, + h265: None, + }) } pub fn new_decoders() -> HwDecoders { - let (best, _) = HwDecoder::best(false, true); + let best = HwDecoder::best(); let mut h264: Option = None; let mut h265: Option = None; let mut fail = false; @@ -242,7 +204,7 @@ impl HwDecoder { } } if fail { - HwDecoder::best(true, true); + check_config_process(true); } HwDecoders { h264, h265 } } @@ -314,31 +276,52 @@ fn get_config(k: &str) -> ResultType { } } -fn set_config(k: &str, v: &CodecInfos) -> ResultType<()> { - match v.serialize() { - Ok(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() { - 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() { - 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(); + let ctx = EncodeContext { + name: String::from(""), + width: 1920, + height: 1080, + pixfmt: DEFAULT_PIXFMT, + align: HW_STRIDE_ALIGN as _, + bitrate: 0, + timebase: DEFAULT_TIME_BASE, + gop: DEFAULT_GOP, + quality: DEFAULT_HW_QUALITY, + rc: DEFAULT_RC, + }; + let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx)); + let decoders = CodecInfo::score(Decoder::avaliable_decoders()); + + if let Ok(old_encoders) = get_config(CFG_KEY_ENCODER) { + if let Ok(old_decoders) = get_config(CFG_KEY_DECODER) { + if encoders == old_encoders && decoders == old_decoders { return; } } - log::error!("Failed to serialize codec info"); } + + if let Ok(encoders) = encoders.serialize() { + if let Ok(decoders) = decoders.serialize() { + 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"); +} + +pub fn check_config_process(force_reset: bool) { + if force_reset { + HwCodecConfig::remove(); + } + if let Ok(exe) = std::env::current_exe() { + std::thread::spawn(move || { + std::process::Command::new(exe) + .arg("--check-hwcodec-config") + .status() + .ok() + }); + }; } diff --git a/src/server.rs b/src/server.rs index a71efaee2..f2d643e1c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -319,6 +319,14 @@ pub async fn start_server(is_server: bool) { log::info!("DISPLAY={:?}", std::env::var("DISPLAY")); log::info!("XAUTHORITY={:?}", std::env::var("XAUTHORITY")); } + #[cfg(feature = "hwcodec")] + { + use std::sync::Once; + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + scrap::hwcodec::check_config_process(false); + }) + } if is_server { std::thread::spawn(move || { @@ -327,15 +335,6 @@ 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();