scrap: check hwconfig in another process
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
feaadcfc96
commit
42c7c5982c
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -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",
|
||||||
|
@ -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
|
||||||
|
@ -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::*;
|
||||||
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
29
src/ipc.rs
29
src/ipc.rs
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
13
src/main.rs
13
src/main.rs
@ -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" {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user