scrap: check hwconfig in another process

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-06-09 19:46:41 +08:00
parent feaadcfc96
commit 42c7c5982c
7 changed files with 141 additions and 36 deletions

2
Cargo.lock generated
View File

@ -2236,7 +2236,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]] [[package]]
name = "hwcodec" name = "hwcodec"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/21pages/hwcodec#6bb387828c9aa69861b707b0f71472b21b5b1711" source = "git+https://github.com/21pages/hwcodec#3ef5b674d3721699daba1f78569eb9c706cb206c"
dependencies = [ dependencies = [
"bindgen", "bindgen",
"cc", "cc",

View File

@ -22,6 +22,7 @@ cli = []
use_samplerate = ["samplerate"] use_samplerate = ["samplerate"]
use_rubato = ["rubato"] use_rubato = ["rubato"]
use_dasp = ["dasp"] use_dasp = ["dasp"]
hwcodec = ["scrap/hwcodec"]
default = ["use_dasp"] default = ["use_dasp"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -35,6 +35,7 @@ lazy_static::lazy_static! {
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load())); static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load())); static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load()));
static ref LOCAL_CONFIG: Arc<RwLock<LocalConfig>> = Arc::new(RwLock::new(LocalConfig::load())); static ref LOCAL_CONFIG: Arc<RwLock<LocalConfig>> = Arc::new(RwLock::new(LocalConfig::load()));
static ref HWCODEC_CONFIG: Arc<RwLock<HwCodecConfig>> = Arc::new(RwLock::new(HwCodecConfig::load()));
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default(); pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default(); pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default();
pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned())); pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned()));
@ -871,6 +872,43 @@ impl LanPeers {
} }
} }
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct HwCodecConfig {
#[serde(default)]
options: HashMap<String, String>,
}
impl HwCodecConfig {
fn load() -> HwCodecConfig {
Config::load_::<HwCodecConfig>("_hwcodec")
}
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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -103,7 +103,7 @@ impl Encoder {
codec: Box::new(hw), codec: Box::new(hw),
}), }),
Err(e) => { Err(e) => {
HwEncoder::best(true); HwEncoder::best(true, true);
Err(e) Err(e)
} }
}, },
@ -114,7 +114,7 @@ impl Encoder {
// TODO // TODO
pub fn update_video_encoder(id: i32, update: EncoderUpdate) { pub fn update_video_encoder(id: i32, update: EncoderUpdate) {
log::info!("update video encoder:{:?}", update); log::info!("encoder update: {:?}", update);
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
{ {
let mut states = PEER_DECODER_STATES.lock().unwrap(); let mut states = PEER_DECODER_STATES.lock().unwrap();
@ -133,7 +133,7 @@ impl Encoder {
} }
let current_encoder_name = HwEncoder::current_name(); let current_encoder_name = HwEncoder::current_name();
if states.len() > 0 { if states.len() > 0 {
let best = HwEncoder::best(false); let (best, _) = HwEncoder::best(false, true);
let enabled_h264 = let enabled_h264 =
best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H264); best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H264);
let enabled_h265 = let enabled_h265 =

View File

@ -4,7 +4,7 @@ use crate::{
}; };
use hbb_common::{ use hbb_common::{
anyhow::{anyhow, Context}, anyhow::{anyhow, Context},
config::LocalConfig, config::HwCodecConfig,
lazy_static, log, lazy_static, log,
message_proto::{H264s, H265s, Message, VideoFrame, H264, H265}, message_proto::{H264s, H265s, Message, VideoFrame, H264, H265},
ResultType, ResultType,
@ -17,12 +17,18 @@ use hwcodec::{
Quality::{self, *}, Quality::{self, *},
RateContorl::{self, *}, RateContorl::{self, *},
}; };
use std::sync::{Arc, Mutex}; use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref HW_ENCODER_NAME: Arc<Mutex<Option<String>>> = Default::default(); static ref HW_ENCODER_NAME: Arc<Mutex<Option<String>>> = Default::default();
} }
const CFG_KEY_ENCODER: &str = "bestHwEncoders";
const CFG_KEY_DECODER: &str = "bestHwDecoders";
const DEFAULT_PIXFMT: AVPixelFormat = AVPixelFormat::AV_PIX_FMT_YUV420P; const DEFAULT_PIXFMT: AVPixelFormat = AVPixelFormat::AV_PIX_FMT_YUV420P;
const DEFAULT_TIME_BASE: [i32; 2] = [1, 30]; const DEFAULT_TIME_BASE: [i32; 2] = [1, 30];
const DEFAULT_GOP: i32 = 60; const DEFAULT_GOP: i32 = 60;
@ -137,12 +143,19 @@ impl EncoderApi for HwEncoder {
} }
impl HwEncoder { impl HwEncoder {
pub fn best(force_reset: bool) -> CodecInfos { /// Get best encoders.
let key = "bestHwEncoders"; ///
/// # Parameter
let config = get_config(key); /// `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() { if !force_reset && config.is_ok() {
config.unwrap() (config.unwrap(), false)
} else { } else {
let ctx = EncodeContext { let ctx = EncodeContext {
name: String::from(""), name: String::from(""),
@ -157,10 +170,12 @@ impl HwEncoder {
rc: DEFAULT_RC, rc: DEFAULT_RC,
}; };
let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx)); let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx));
let _ = set_config(key, &encoders) if write {
.map_err(|e| log::error!("{:?}", e)) let _ = set_config(CFG_KEY_ENCODER, &encoders)
.ok(); .map_err(|e| log::error!("{:?}", e))
encoders .ok();
}
(encoders, true)
} }
} }
@ -234,23 +249,24 @@ pub struct HwDecoders {
} }
impl HwDecoder { impl HwDecoder {
/// H264, H265 decoder info with the highest score. /// See HwEncoder::best
fn best(force_reset: bool) -> CodecInfos { fn best(force_reset: bool, write: bool) -> (CodecInfos, bool) {
let key = "bestHwDecoders"; let config = get_config(CFG_KEY_DECODER);
let config = get_config(key);
if !force_reset && config.is_ok() { if !force_reset && config.is_ok() {
config.unwrap() (config.unwrap(), false)
} else { } else {
let decoders = CodecInfo::score(Decoder::avaliable_decoders()); let decoders = CodecInfo::score(Decoder::avaliable_decoders());
set_config(key, &decoders) if write {
.map_err(|e| log::error!("{:?}", e)) set_config(CFG_KEY_DECODER, &decoders)
.ok(); .map_err(|e| log::error!("{:?}", e))
decoders .ok();
}
(decoders, true)
} }
} }
pub fn new_decoders() -> HwDecoders { pub fn new_decoders() -> HwDecoders {
let best = HwDecoder::best(false); let (best, _) = HwDecoder::best(false, true);
let mut h264: Option<HwDecoder> = None; let mut h264: Option<HwDecoder> = None;
let mut h265: Option<HwDecoder> = None; let mut h265: Option<HwDecoder> = None;
let mut fail = false; let mut fail = false;
@ -268,14 +284,7 @@ impl HwDecoder {
} }
} }
if fail { if fail {
HwDecoder::best(true); HwDecoder::best(true, true);
}
if h264.is_some() {
log::info!("h264 decoder:{:?}", h264.as_ref().unwrap().info);
}
if h265.is_some() {
log::info!("h265 decoder:{:?}", h265.as_ref().unwrap().info);
} }
HwDecoders { h264, h265 } HwDecoders { h264, h265 }
} }
@ -336,7 +345,7 @@ impl HwDecoderImage<'_> {
} }
fn get_config(k: &str) -> ResultType<CodecInfos> { fn get_config(k: &str) -> ResultType<CodecInfos> {
let v = LocalConfig::get_option(k); let v = HwCodecConfig::get_option(k);
match CodecInfos::deserialize(&v) { match CodecInfos::deserialize(&v) {
Ok(v) => Ok(v), Ok(v) => Ok(v),
Err(_) => Err(anyhow!("Failed to get config:{}", k)), Err(_) => Err(anyhow!("Failed to get config:{}", k)),
@ -346,9 +355,26 @@ fn get_config(k: &str) -> ResultType<CodecInfos> {
fn set_config(k: &str, v: &CodecInfos) -> ResultType<()> { fn set_config(k: &str, v: &CodecInfos) -> ResultType<()> {
match v.serialize() { match v.serialize() {
Ok(v) => { Ok(v) => {
LocalConfig::set_option(k.to_owned(), v); HwCodecConfig::set_option(k.to_owned(), v);
Ok(()) Ok(())
} }
Err(_) => Err(anyhow!("Failed to set config:{}", k)), Err(_) => Err(anyhow!("Failed to set config:{}", k)),
} }
} }
pub fn check_config() -> Option<HashMap<String, String>> {
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),
]));
}
}
log::error!("Failed to serialize codec info");
}
None
}

View File

@ -1,6 +1,8 @@
use crate::rendezvous_mediator::RendezvousMediator; use crate::rendezvous_mediator::RendezvousMediator;
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
pub use clipboard::ClipbaordFile; pub use clipboard::ClipbaordFile;
#[cfg(feature = "hwcodec")]
use hbb_common::config::HwCodecConfig;
use hbb_common::{ use hbb_common::{
allow_err, bail, bytes, allow_err, bail, bytes,
bytes_codec::BytesCodec, bytes_codec::BytesCodec,
@ -63,7 +65,7 @@ pub enum FS {
WriteOffset { WriteOffset {
id: i32, id: i32,
file_num: i32, file_num: i32,
offset_blk: u32 offset_blk: u32,
}, },
CheckDigest { CheckDigest {
id: i32, id: i32,
@ -116,6 +118,8 @@ pub enum Data {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
ClipbaordFile(ClipbaordFile), ClipbaordFile(ClipbaordFile),
ClipboardFileEnabled(bool), ClipboardFileEnabled(bool),
#[cfg(feature = "hwcodec")]
HwCodecConfig(Option<HashMap<String, String>>),
} }
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
@ -325,6 +329,12 @@ async fn handle(data: Data, stream: &mut Connection) {
.await .await
); );
} }
#[cfg(feature = "hwcodec")]
Data::HwCodecConfig(Some(config)) => {
for (k, v) in config {
HwCodecConfig::set_option(k, v);
}
}
_ => {} _ => {}
} }
} }
@ -624,3 +634,20 @@ pub async fn set_socks(value: config::Socks5Server) -> ResultType<()> {
.await?; .await?;
Ok(()) 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);
}
}
}
}

View File

@ -70,6 +70,15 @@ fn main() {
} }
if args.is_empty() { if args.is_empty() {
std::thread::spawn(move || start_server(false)); 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 { } else {
#[cfg(windows)] #[cfg(windows)]
{ {
@ -104,6 +113,10 @@ fn main() {
"".to_owned() "".to_owned()
)); ));
return; return;
} else if args[0] == "--check-hwcodec-config" {
#[cfg(feature = "hwcodec")]
ipc::check_hwcodec_config();
return;
} }
} }
if args[0] == "--remove" { if args[0] == "--remove" {