From 304e0e465db6c4bf3434fa80d7367f18a1e16160 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 16 Nov 2024 22:31:28 +0800 Subject: [PATCH] if av1 is not slow in test, av1 takes precedence over vp9 (#9938) Signed-off-by: 21pages --- libs/hbb_common/src/config.rs | 1 + libs/scrap/src/common/codec.rs | 94 ++++++++++++++++++++++++++++++++-- src/flutter_ffi.rs | 1 + src/server.rs | 2 +- 4 files changed, 93 insertions(+), 5 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 5807dafa5..dd4abaf9d 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -2238,6 +2238,7 @@ pub mod keys { pub const OPTION_ENABLE_ANDROID_SOFTWARE_ENCODING_HALF_SCALE: &str = "enable-android-software-encoding-half-scale"; pub const OPTION_ENABLE_TRUSTED_DEVICES: &str = "enable-trusted-devices"; + pub const OPTION_AV1_TEST: &str = "av1-test"; // buildin options pub const OPTION_DISPLAY_NAME: &str = "display-name"; diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index dad924c86..0e4b65da6 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -1,6 +1,5 @@ use std::{ collections::HashMap, - ffi::c_void, ops::{Deref, DerefMut}, sync::{Arc, Mutex}, }; @@ -264,15 +263,20 @@ impl Encoder { .unwrap_or((PreferCodec::Auto.into(), 0)); let preference = most_frequent.enum_value_or(PreferCodec::Auto); - // auto: h265 > h264 > vp9/vp8 - let mut auto_codec = CodecFormat::VP9; + // auto: h265 > h264 > av1/vp9/vp8 + let av1_test = Config::get_option(hbb_common::config::keys::OPTION_AV1_TEST) != "N"; + let mut auto_codec = if av1_useable && av1_test { + CodecFormat::AV1 + } else { + CodecFormat::VP9 + }; if h264_useable { auto_codec = CodecFormat::H264; } if h265_useable { auto_codec = CodecFormat::H265; } - if auto_codec == CodecFormat::VP9 { + if auto_codec == CodecFormat::VP9 || auto_codec == CodecFormat::AV1 { let mut system = System::new(); system.refresh_memory(); if vp8_useable && system.total_memory() <= 4 * 1024 * 1024 * 1024 { @@ -982,3 +986,85 @@ fn disable_av1() -> bool { // disable it for all 32 bit platforms std::mem::size_of::() == 4 } + +#[cfg(not(target_os = "ios"))] +pub fn test_av1() { + use hbb_common::config::keys::OPTION_AV1_TEST; + use std::sync::Once; + if disable_av1() || !Config::get_option(OPTION_AV1_TEST).is_empty() { + log::info!("skip test av1"); + return; + } + + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + let f = || { + let (width, height, quality, keyframe_interval, i444) = + (1920, 1080, Quality::Balanced, None, false); + let Ok(mut av1) = AomEncoder::new( + EncoderCfg::AOM(AomEncoderConfig { + width, + height, + quality, + keyframe_interval, + }), + i444, + ) else { + return false; + }; + let Ok(mut vp9) = VpxEncoder::new( + EncoderCfg::VPX(VpxEncoderConfig { + codec: VpxVideoCodecId::VP9, + width, + height, + quality, + keyframe_interval, + }), + i444, + ) else { + return true; + }; + let frame_count = 10; + let mut yuv = vec![0u8; (width * height * 3 / 2) as usize]; + let start = Instant::now(); + for i in 0..frame_count { + for w in 0..width { + yuv[w as usize] = i as u8; + } + if av1.encode(0, &yuv, super::STRIDE_ALIGN).is_err() { + log::debug!("av1 encode failed"); + if i == 0 { + return false; + } + } + } + let av1_time = start.elapsed(); + log::info!("av1 time: {:?}", av1_time); + if av1_time < std::time::Duration::from_millis(250) { + return true; + } + let start = Instant::now(); + for i in 0..frame_count { + for w in 0..width { + yuv[w as usize] = i as u8; + } + if vp9.encode(0, &yuv, super::STRIDE_ALIGN).is_err() { + log::debug!("vp9 encode failed"); + if i == 0 { + return true; + } + } + } + let vp9_time = start.elapsed(); + log::info!("vp9 time: {:?}", vp9_time); + av1_time * 2 / 3 < vp9_time + }; + std::thread::spawn(move || { + let v = f(); + Config::set_option( + OPTION_AV1_TEST.to_string(), + if v { "Y" } else { "N" }.to_string(), + ); + }); + }); +} diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 7a0c5e874..3943f30f1 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -2332,6 +2332,7 @@ pub mod server_side { } } std::thread::spawn(move || start_server(true)); + scrap::codec::test_av1(); } #[no_mangle] diff --git a/src/server.rs b/src/server.rs index eca20b829..02c4df36c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -500,8 +500,8 @@ pub async fn start_server(is_server: bool, no_server: bool) { #[cfg(target_os = "windows")] crate::platform::try_kill_broker(); #[cfg(feature = "hwcodec")] - #[cfg(not(any(target_os = "android", target_os = "ios")))] scrap::hwcodec::start_check_process(); + scrap::codec::test_av1(); crate::RendezvousMediator::start_all().await; } else { match crate::ipc::connect(1000, "").await {