From d70b0cdd4fcd9925e005719e2a6e638e5bfb4884 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 13 May 2024 20:24:50 +0800 Subject: [PATCH] Not require both max-width and max-height of mediacodec larger than (#8036) screen width and screen height * Only use hardware codec, when api < 29, judge with codec name prefix. Signed-off-by: 21pages --- .../com/carriez/flutter_hbb/MainActivity.kt | 11 +++++++-- libs/scrap/src/android/ffi.rs | 2 ++ libs/scrap/src/common/hwcodec.rs | 23 ++++++++++++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt index ab51b20d1..076fac38c 100644 --- a/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt +++ b/flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt @@ -264,8 +264,12 @@ class MainActivity : FlutterActivity() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { hw = codec.isHardwareAccelerated } else { - if (listOf("OMX.google.", "OMX.SEC.", "c2.android").any { codec.name.startsWith(it) }) { + // https://chromium.googlesource.com/external/webrtc/+/HEAD/sdk/android/src/java/org/webrtc/MediaCodecUtils.java#29 + // https://chromium.googlesource.com/external/webrtc/+/master/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java#229 + if (listOf("OMX.google.", "OMX.SEC.", "c2.android").any { codec.name.startsWith(it, true) }) { hw = false + } else if (listOf("c2.qti", "OMX.qcom.video", "OMX.Exynos", "OMX.hisi", "OMX.MTK", "OMX.Intel", "OMX.Nvidia").any { codec.name.startsWith(it, true) }) { + hw = true } } codecObject.put("hw", hw) @@ -280,7 +284,8 @@ class MainActivity : FlutterActivity() { val caps = codec.getCapabilitiesForType(mime_type) var usable = true; if (codec.isEncoder) { - if (!caps.videoCapabilities.isSizeSupported(w,h) || !caps.videoCapabilities.isSizeSupported(h,w)) { + // Encoder‘s max_height and max_width are interchangeable + if (!caps.videoCapabilities.isSizeSupported(w,h) && !caps.videoCapabilities.isSizeSupported(h,w)) { usable = false } } @@ -309,6 +314,8 @@ class MainActivity : FlutterActivity() { } val result = JSONObject() result.put("version", Build.VERSION.SDK_INT) + result.put("w", w) + result.put("h", h) result.put("codecs", codecArray) FFI.setCodecInfo(result.toString()) } diff --git a/libs/scrap/src/android/ffi.rs b/libs/scrap/src/android/ffi.rs index a604166a7..02f73667a 100644 --- a/libs/scrap/src/android/ffi.rs +++ b/libs/scrap/src/android/ffi.rs @@ -178,6 +178,8 @@ pub struct MediaCodecInfo { #[derive(Debug, Deserialize, Clone)] pub struct MediaCodecInfos { pub version: usize, + pub w: usize, + pub h: usize, pub codecs: Vec, } diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index a1dbeae18..83569150b 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -416,6 +416,7 @@ fn get_config() -> ResultType { #[cfg(target_os = "android")] { let info = crate::android::ffi::get_codec_info(); + log::info!("all codec info: {info:?}"); struct T { name_prefix: &'static str, data_format: DataFormat, @@ -440,16 +441,26 @@ fn get_config() -> ResultType { c.is_encoder && c.mime_type.as_str() == get_mime_type(t.data_format) && c.nv12 + && c.hw == Some(true) //only use hardware codec }) .collect(); log::debug!("available {:?} encoders: {codecs:?}", t.data_format); + let screen_wh = std::cmp::max(info.w, info.h); let mut best = None; - if let Some(c) = codecs.iter().find(|c| c.hw == Some(true)) { - best = Some(c.name.clone()); - } else if let Some(c) = codecs.iter().find(|c| c.hw == None) { - best = Some(c.name.clone()); - } else if let Some(c) = codecs.first() { - best = Some(c.name.clone()); + if let Some(codec) = codecs + .iter() + .find(|c| c.max_width >= screen_wh && c.max_height >= screen_wh) + { + best = Some(codec.name.clone()); + } else { + // find the max resolution + let mut max_area = 0; + for codec in codecs.iter() { + if codec.max_width * codec.max_height > max_area { + best = Some(codec.name.clone()); + max_area = codec.max_width * codec.max_height; + } + } } if let Some(best) = best { e.push(CodecInfo {