From a8ee9552a07afa8fa5b1d1a0d26725a46a32863d Mon Sep 17 00:00:00 2001 From: mofeng-git Date: Sat, 5 Sep 2026 14:10:53 +0800 Subject: [PATCH] =?UTF-8?q?perf(video):=20=E4=BD=BF=E7=94=A8=E6=9C=89?= =?UTF-8?q?=E7=95=8C=20VBR=20=E4=BC=98=E5=8C=96=20H264=20=E7=A0=81?= =?UTF-8?q?=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit H264 编码器探测与初始化使用 VBR,将峰值码率和缓冲区限制为目标码率的两倍。动态调整码率时同步更新限制,并保留 QSV 的专用处理。 --- libs/hwcodec/cpp/common/util.cpp | 12 ++++++++++++ src/video/codec/h264.rs | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libs/hwcodec/cpp/common/util.cpp b/libs/hwcodec/cpp/common/util.cpp index 0894f4eb..a2762aab 100644 --- a/libs/hwcodec/cpp/common/util.cpp +++ b/libs/hwcodec/cpp/common/util.cpp @@ -397,6 +397,14 @@ struct CodecOptions { bool set_rate_control(AVCodecContext *c, const std::string &name, int rc, int q) { + // Remote-desktop content is usually sparse. VBR avoids padding static + // frames up to the target bitrate while allowing short bursts for screen + // changes. Keep those bursts bounded at twice the target bitrate. + if (rc == RC_VBR && c->bit_rate > 0) { + c->rc_max_rate = c->bit_rate * 2; + c->rc_buffer_size = c->rc_max_rate; + } + if (name.find("vaapi") != std::string::npos && rc == RC_CQ) { // Used only after the normal bitrate-based VAAPI initialization fails. // Some drivers, including Intel iHD on Jasper Lake, expose CQP as their @@ -495,6 +503,10 @@ bool set_others(void *priv_data, const std::string &name) { bool change_bit_rate(AVCodecContext *c, const std::string &name, int kbs) { if (kbs > 0) { c->bit_rate = kbs * 1000; + if (c->rc_max_rate > 0 && name.find("qsv") == std::string::npos) { + c->rc_max_rate = c->bit_rate * 2; + c->rc_buffer_size = c->rc_max_rate; + } if (name.find("qsv") != std::string::npos) { c->rc_max_rate = c->bit_rate; } diff --git a/src/video/codec/h264.rs b/src/video/codec/h264.rs index 13d7a3a8..8b0ac59a 100644 --- a/src/video/codec/h264.rs +++ b/src/video/codec/h264.rs @@ -198,7 +198,7 @@ pub fn get_available_encoders(width: u32, height: u32) -> Vec { align: 1, fps: 30, gop: 30, - rc: RateControl::RC_CBR, + rc: RateControl::RC_VBR, quality: Quality::Quality_Low, // Use low quality preset for fastest encoding (ultrafast) kbs: 2000, q: 23, @@ -297,7 +297,7 @@ impl H264Encoder { align: 1, fps: config.fps as i32, gop: config.gop_size as i32, - rc: RateControl::RC_CBR, + rc: RateControl::RC_VBR, quality: Quality::Quality_Low, // Use low quality preset for fastest encoding (lowest latency) kbs: config.bitrate_kbps as i32, q: 23,