hwcodec, only process that start ipc server start check process (#8325)

check process send config to ipc server, other process get config from ipc server. Process will save config to toml, and the toml will be used if the config is none.

when start check process: ipc server process start or option changed
from disable to enable

when get config: main window start or option changed from disable to
enable, start_video_audio_threads.

Only windows implements signature, which is used to mark whether the gpu software and hardware information changes. After reboot, the signature doesn't change. https://asawicki.info/news_1773_how_to_programmatically_check_graphics_driver_version, use dxgi way to get software version, it's not consistent with the visible driver version, after updating intel driver with small version change, the signature doesn't change. Linux doesn't use toml file.

Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
21pages
2024-06-12 20:40:35 +08:00
committed by GitHub
parent 0f10a88b23
commit 610009528b
10 changed files with 393 additions and 210 deletions

View File

@@ -2132,6 +2132,7 @@ where
std::thread::spawn(move || {
#[cfg(windows)]
sync_cpu_usage();
get_hwcodec_config();
let mut handler_controller_map = HashMap::new();
// let mut count = Vec::new();
// let mut duration = std::time::Duration::ZERO;
@@ -2333,6 +2334,27 @@ pub fn start_audio_thread() -> MediaSender {
audio_sender
}
fn get_hwcodec_config() {
// for sciter and unilink
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
{
use std::sync::Once;
static ONCE: Once = Once::new();
ONCE.call_once(|| {
let start = std::time::Instant::now();
if let Err(e) = crate::ipc::get_hwcodec_config_from_server() {
log::error!(
"failed to get hwcodec config: {e:?}, elapsed: {:?}",
start.elapsed()
);
} else {
log::info!("{:?} used to get hwcodec config", start.elapsed());
}
});
}
}
#[cfg(windows)]
fn sync_cpu_usage() {
use std::sync::Once;

View File

@@ -412,7 +412,7 @@ pub fn core_main() -> Option<Vec<String>> {
return None;
} else if args[0] == "--check-hwcodec-config" {
#[cfg(feature = "hwcodec")]
scrap::hwcodec::check_available_hwcodec();
crate::ipc::hwcodec_process();
return None;
} else if args[0] == "--cm" {
// call connection manager to establish connections

View File

@@ -239,6 +239,7 @@ pub enum Data {
VideoConnCount(Option<usize>),
// Although the key is not neccessary, it is used to avoid hardcoding the key.
WaylandScreencastRestoreToken((String, String)),
HwCodecConfig(Option<String>),
}
#[tokio::main(flavor = "current_thread")]
@@ -523,12 +524,26 @@ async fn handle(data: Data, stream: &mut Connection) {
.await
);
}
Data::CheckHwcodec =>
{
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
if crate::platform::is_root() {
scrap::hwcodec::start_check_process(true);
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
Data::CheckHwcodec => {
scrap::hwcodec::start_check_process();
}
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
Data::HwCodecConfig(c) => {
match c {
None => {
let v = match scrap::hwcodec::HwCodecConfig::get_set_value() {
Some(v) => Some(serde_json::to_string(&v).unwrap_or_default()),
None => None,
};
allow_err!(stream.send(&Data::HwCodecConfig(v)).await);
}
Some(v) => {
// --server and portable
scrap::hwcodec::HwCodecConfig::set(v);
}
}
}
Data::WaylandScreencastRestoreToken((key, value)) => {
@@ -1025,6 +1040,83 @@ pub async fn notify_server_to_check_hwcodec() -> ResultType<()> {
Ok(())
}
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
#[tokio::main(flavor = "current_thread")]
pub async fn get_hwcodec_config_from_server() -> ResultType<()> {
if !scrap::codec::enable_hwcodec_option() || scrap::hwcodec::HwCodecConfig::already_set() {
return Ok(());
}
let mut c = connect(50, "").await?;
c.send(&Data::HwCodecConfig(None)).await?;
if let Some(Data::HwCodecConfig(v)) = c.next_timeout(50).await? {
match v {
Some(v) => {
scrap::hwcodec::HwCodecConfig::set(v);
return Ok(());
}
None => {
bail!("hwcodec config is none");
}
}
}
bail!("failed to get hwcodec config");
}
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
pub fn client_get_hwcodec_config_thread(wait_sec: u64) {
static ONCE: std::sync::Once = std::sync::Once::new();
if !crate::platform::is_installed()
|| !scrap::codec::enable_hwcodec_option()
|| scrap::hwcodec::HwCodecConfig::already_set()
{
return;
}
ONCE.call_once(move || {
std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(1));
let mut intervals: Vec<u64> = vec![wait_sec, 3, 3, 6, 9];
for i in intervals.drain(..) {
if i > 0 {
std::thread::sleep(std::time::Duration::from_secs(i));
}
if get_hwcodec_config_from_server().is_ok() {
break;
}
}
});
});
}
#[cfg(feature = "hwcodec")]
#[tokio::main(flavor = "current_thread")]
pub async fn hwcodec_process() {
let s = scrap::hwcodec::check_available_hwcodec();
for _ in 0..5 {
match crate::ipc::connect(1000, "").await {
Ok(mut conn) => {
match conn
.send(&crate::ipc::Data::HwCodecConfig(Some(s.clone())))
.await
{
Ok(()) => {
log::info!("send ok");
break;
}
Err(e) => {
log::error!("send failed: {e:?}");
}
}
}
Err(e) => {
log::error!("connect failed: {e:?}");
}
}
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
#[tokio::main(flavor = "current_thread")]
pub async fn get_wayland_screencast_restore_token(key: String) -> ResultType<String> {
let v = handle_wayland_screencast_restore_token(key, "get".to_owned()).await?;

View File

@@ -459,9 +459,6 @@ 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")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
scrap::hwcodec::start_check_process(false);
#[cfg(windows)]
hbb_common::platform::windows::start_cpu_performance_monitor();
@@ -489,6 +486,9 @@ pub async fn start_server(is_server: bool) {
tokio::spawn(async { sync_and_watch_config_dir().await });
#[cfg(target_os = "windows")]
crate::platform::try_kill_broker();
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
scrap::hwcodec::start_check_process();
crate::RendezvousMediator::start_all().await;
} else {
match crate::ipc::connect(1000, "").await {
@@ -509,6 +509,9 @@ pub async fn start_server(is_server: bool) {
}
}
}
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
crate::ipc::client_get_hwcodec_config_thread(0);
}
Err(err) => {
log::info!("server not started (will try to start): {}", err);

View File

@@ -172,15 +172,13 @@ pub fn get_option<T: AsRef<str>>(key: T) -> String {
#[inline]
#[cfg(target_os = "macos")]
pub fn use_texture_render() -> bool {
cfg!(feature = "flutter")
&& LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) == "Y"
cfg!(feature = "flutter") && LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) == "Y"
}
#[inline]
#[cfg(any(target_os = "windows", target_os = "linux"))]
pub fn use_texture_render() -> bool {
cfg!(feature = "flutter")
&& LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) != "N"
cfg!(feature = "flutter") && LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) != "N"
}
#[inline]
@@ -1398,9 +1396,16 @@ pub fn check_hwcodec() {
#[cfg(feature = "hwcodec")]
#[cfg(any(target_os = "windows", target_os = "linux"))]
{
scrap::hwcodec::start_check_process(true);
if crate::platform::is_installed() {
ipc::notify_server_to_check_hwcodec().ok();
}
use std::sync::Once;
static ONCE: Once = Once::new();
ONCE.call_once(|| {
if crate::platform::is_installed() {
ipc::notify_server_to_check_hwcodec().ok();
ipc::client_get_hwcodec_config_thread(3);
} else {
scrap::hwcodec::start_check_process();
}
})
}
}