From 16fd96aa96ddf3f40672c4e0c1c94e34b65bf9f1 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 1 Jun 2022 17:52:21 +0800 Subject: [PATCH] fix android bit rate --- Cargo.lock | 1 + .../com/carriez/flutter_hbb/MainService.kt | 8 +++- libs/scrap/Cargo.toml | 1 + libs/scrap/src/common/android.rs | 40 +++++++++++++------ libs/scrap/src/common/mod.rs | 8 ++-- libs/scrap/src/lib.rs | 4 +- src/server/video_service.rs | 10 +++++ 7 files changed, 51 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6942ef72..a91100885 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4265,6 +4265,7 @@ dependencies = [ "quest", "repng", "serde 1.0.136", + "serde_json 1.0.79", "target_build_utils", "tracing", "webm", diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt index 4a1b8c06f..62376ae5f 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt @@ -72,7 +72,13 @@ class MainService : Service() { @Keep fun rustGetByName(name: String): String { return when (name) { - "screen_size" -> "${SCREEN_INFO.width}:${SCREEN_INFO.height}" + "screen_size" -> { + JSONObject().apply { + put("width",SCREEN_INFO.width) + put("height",SCREEN_INFO.height) + put("scale",SCREEN_INFO.scale) + }.toString() + } else -> "" } } diff --git a/libs/scrap/Cargo.toml b/libs/scrap/Cargo.toml index 00c4509ab..de39534ac 100644 --- a/libs/scrap/Cargo.toml +++ b/libs/scrap/Cargo.toml @@ -28,6 +28,7 @@ android_logger = "0.10" jni = "0.19" lazy_static = "1.4" log = "0.4" +serde_json = "1.0" [target.'cfg(not(target_os = "android"))'.dev-dependencies] repng = "0.2" diff --git a/libs/scrap/src/common/android.rs b/libs/scrap/src/common/android.rs index 555e6cd7b..1975a6505 100644 --- a/libs/scrap/src/common/android.rs +++ b/libs/scrap/src/common/android.rs @@ -1,11 +1,13 @@ use crate::android::ffi::*; use crate::rgba_to_i420; use lazy_static::lazy_static; +use serde_json::Value; +use std::collections::HashMap; use std::io; use std::sync::Mutex; lazy_static! { - static ref SCREEN_SIZE: Mutex<(u16, u16)> = Mutex::new((0, 0)); + static ref SCREEN_SIZE: Mutex<(u16, u16, u16)> = Mutex::new((0, 0, 0)); // (width, height, scale) } pub struct Capturer { @@ -65,9 +67,7 @@ impl Display { pub fn primary() -> io::Result { let mut size = SCREEN_SIZE.lock().unwrap(); if size.0 == 0 || size.1 == 0 { - let (w, h) = get_size().unwrap_or((0, 0)); - size.0 = w; - size.1 = h; + *size = get_size().unwrap_or_default(); } Ok(Display { default: true, @@ -111,19 +111,33 @@ impl Display { pub fn refresh_size() { let mut size = SCREEN_SIZE.lock().unwrap(); - let (w, h) = get_size().unwrap_or((0, 0)); - size.0 = w; - size.1 = h; + *size = get_size().unwrap_or_default(); + } + + // Big android screen size will be shrinked, to improve performance when screen-capturing and encoding + // e.g 2280x1080 size will be set to 1140x540, and `scale` is 2 + // need to multiply by `4` (2*2) when compute the bitrate + pub fn fix_quality() -> u16 { + let scale = SCREEN_SIZE.lock().unwrap().2; + if scale <= 0 { + 1 + } else { + scale * scale + } } } -fn get_size() -> Option<(u16, u16)> { +fn get_size() -> Option<(u16, u16, u16)> { let res = call_main_service_get_by_name("screen_size").ok()?; - if res.len() > 0 { - let mut sp = res.split(":"); - let w = sp.next()?.parse::().ok()?; - let h = sp.next()?.parse::().ok()?; - return Some((w, h)); + if let Ok(json) = serde_json::from_str::>(&res) { + if let (Some(Value::Number(w)), Some(Value::Number(h)), Some(Value::Number(scale))) = + (json.get("width"), json.get("height"), json.get("scale")) + { + let w = w.as_i64()? as _; + let h = h.as_i64()? as _; + let scale = scale.as_i64()? as _; + return Some((w, h, scale)); + } } None } diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index dd2b4295a..108a4ae31 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -19,7 +19,7 @@ cfg_if! { } else if #[cfg(dxgi)] { mod dxgi; pub use self::dxgi::*; - } else if #[cfg(android)] { + } else if #[cfg(target_os = "android")] { mod android; pub use self::android::*; }else { @@ -36,13 +36,11 @@ mod vpx; #[inline] pub fn would_block_if_equal(old: &mut Vec, b: &[u8]) -> std::io::Result<()> { - let b = unsafe { - std::slice::from_raw_parts::(b.as_ptr() as _, b.len() / 16) - }; + let b = unsafe { std::slice::from_raw_parts::(b.as_ptr() as _, b.len() / 16) }; if b == &old[..] { return Err(std::io::ErrorKind::WouldBlock.into()); } old.resize(b.len(), 0); old.copy_from_slice(b); Ok(()) -} \ No newline at end of file +} diff --git a/libs/scrap/src/lib.rs b/libs/scrap/src/lib.rs index 4d481ed26..504f0a4b3 100644 --- a/libs/scrap/src/lib.rs +++ b/libs/scrap/src/lib.rs @@ -14,13 +14,13 @@ pub mod quartz; #[cfg(x11)] pub mod x11; -#[cfg(all(x11, feature="wayland"))] +#[cfg(all(x11, feature = "wayland"))] pub mod wayland; #[cfg(dxgi)] pub mod dxgi; -#[cfg(android)] +#[cfg(target_os = "android")] pub mod android; mod common; diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 17b545426..8c0edba43 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -567,5 +567,15 @@ fn get_quality(w: usize, h: usize, q: i32) -> (u32, u32, u32, i32) { let bitrate = q >> 8 & 0xFF; let quantizer = q & 0xFF; let b = ((w * h) / 1000) as u32; + + #[cfg(target_os = "android")] + { + // fix when andorid screen shrinks + let fix = Display::fix_quality() as u32; + log::debug!("Android screen, fix quality:{}", fix); + let b = b * fix; + return (bitrate as u32 * b / 100, quantizer as _, 56, 7); + } + (bitrate as u32 * b / 100, quantizer as _, 56, 7) }