From c7308dbbc9c8e882667b4de8b7bd3a852dfc3675 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 27 May 2024 19:34:40 +0800 Subject: [PATCH] fix mediacodec bad encoding quality (#8159) Signed-off-by: 21pages --- Cargo.lock | 4 ++-- libs/scrap/src/common/hwcodec.rs | 35 +++++++++++++++++++------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f7f0be6a..bb948aa79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3037,8 +3037,8 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hwcodec" -version = "0.4.11" -source = "git+https://github.com/21pages/hwcodec#a5864080e41836b94feb9f73732280c651162fec" +version = "0.4.12" +source = "git+https://github.com/21pages/hwcodec#6fbafe7dd25adad5e897b3192b2b40b720a9b118" dependencies = [ "bindgen 0.59.2", "cc", diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index ddc20cb95..2c0018245 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -14,14 +14,16 @@ use hbb_common::{ serde_json, ResultType, }; use hwcodec::{ - common::DataFormat, + common::{ + DataFormat, + Quality::{self, *}, + RateControl::{self, *}, + }, ffmpeg::AVPixelFormat, ffmpeg_ram::{ decode::{DecodeContext, DecodeFrame, Decoder}, encode::{EncodeContext, EncodeFrame, Encoder}, CodecInfo, - Quality::{self, *}, - RateControl::{self, *}, }, }; @@ -29,10 +31,6 @@ const DEFAULT_PIXFMT: AVPixelFormat = AVPixelFormat::AV_PIX_FMT_NV12; pub const DEFAULT_TIME_BASE: [i32; 2] = [1, 30]; const DEFAULT_GOP: i32 = i32::MAX; const DEFAULT_HW_QUALITY: Quality = Quality_Default; -#[cfg(target_os = "android")] -const DEFAULT_RC: RateControl = RC_VBR; // android cbr poor quality -#[cfg(not(target_os = "android"))] -const DEFAULT_RC: RateControl = RC_CBR; #[derive(Debug, Clone)] pub struct HwRamEncoderConfig { @@ -59,6 +57,7 @@ impl EncoderApi for HwRamEncoder { { match cfg { EncoderCfg::HWRAM(config) => { + let rc = Self::rate_control(&config); let b = Self::convert_quality(&config.name, config.quality); let base_bitrate = base_bitrate(config.width as _, config.height as _); let mut bitrate = base_bitrate * b / 100; @@ -78,7 +77,8 @@ impl EncoderApi for HwRamEncoder { timebase: DEFAULT_TIME_BASE, gop, quality: DEFAULT_HW_QUALITY, - rc: DEFAULT_RC, + rc, + q: -1, thread_count: codec_thread_num(16) as _, // ffmpeg's thread_count is used for cpu }; let format = match Encoder::format_from_name(config.name.clone()) { @@ -175,6 +175,7 @@ impl EncoderApi for HwRamEncoder { self.encoder.set_bitrate(bitrate as _).ok(); self.bitrate = bitrate; } + self.config.quality = quality; Ok(()) } @@ -232,6 +233,14 @@ impl HwRamEncoder { } } + fn rate_control(config: &HwRamEncoderConfig) -> RateControl { + #[cfg(target_os = "android")] + if config.name.contains("mediacodec") { + return RC_VBR; + } + RC_CBR + } + pub fn convert_quality(name: &str, quality: crate::codec::Quality) -> u32 { use crate::codec::Quality; let quality = match quality { @@ -241,11 +250,8 @@ impl HwRamEncoder { Quality::Custom(b) => b, }; let factor = if name.contains("mediacodec") { - if name.contains("h264") { - 6 - } else { - 3 - } + // https://stackoverflow.com/questions/26110337/what-are-valid-bit-rates-to-set-for-mediacodec?rq=3 + 5 } else { 1 }; @@ -510,7 +516,8 @@ pub fn check_available_hwcodec() { timebase: DEFAULT_TIME_BASE, gop: DEFAULT_GOP, quality: DEFAULT_HW_QUALITY, - rc: DEFAULT_RC, + rc: RC_CBR, + q: -1, thread_count: 4, }; #[cfg(feature = "vram")]