Files
remote/agent/src/bin/encbench.rs
T
dev-team e7472fa12f perf(agent): 60fps上限/零拷贝转换/多线程编码/发送缓冲512KB + encbench基准
- capture: min_frame 33→16ms,RC 60fps;with_mapped 映射窗口内直接 BGRA→YUV(行距连续零拷贝)
- capture: num_threads(4) + 每120帧输出 convert/encode 耗时(实测:convert 2ms,encode 41ms/帧真实工况)
- agent: send_window 2MB→512KB,E2E 排队天花板 ~0.15s(修复 E2E 633ms 红)
- encbench: 1080p 编码基准(合成 5ms/帧,真实工况 41ms/帧 → 软编 1080p 上限 ~24fps,60fps 需 NVENC)
- tools/bench.md
2026-10-23 10:02:41 +08:00

60 lines
2.3 KiB
Rust

//! 编码基准:1080p 噪声帧(最恶劣压缩工况)对比单线程与 4 线程 openh264。
//! 运行:cargo run --release -p agent --bin encbench
use openh264::encoder::{
BitRate, Encoder, EncoderConfig, FrameRate, IntraFramePeriod, RateControlMode, UsageType,
};
use openh264::formats::{BgraSliceU8, YUVBuffer};
use openh264::OpenH264API;
use std::time::Instant;
fn bench(threads: u16, frames: usize) -> f64 {
let mut enc = Encoder::with_api_config(
OpenH264API::from_source(),
EncoderConfig::new()
.bitrate(BitRate::from_bps(5_000_000))
.max_frame_rate(FrameRate::from_hz(30.0))
.rate_control_mode(RateControlMode::Bitrate)
.usage_type(UsageType::ScreenContentRealTime)
.intra_frame_period(IntraFramePeriod::from_num_frames(300))
.num_threads(threads),
)
.expect("encoder");
// 预生成 10 张不同噪声帧轮换(保证每帧 P 帧都真实编码,避免运动估计空转)
let mut frames_in = Vec::with_capacity(10);
for f in 0..10u32 {
let mut frame = vec![0u8; 1920 * 1080 * 4];
let mut seed = 12345u32.wrapping_add(f * 7919);
for px in frame.chunks_exact_mut(4) {
seed = seed.wrapping_mul(1103515245).wrapping_add(12345);
px.copy_from_slice(&seed.to_le_bytes());
}
frames_in.push(YUVBuffer::from_bgra8_source(BgraSliceU8::new(&frame, (1920, 1080))));
}
// 预热 5 帧(首帧 IDR、线程池初始化)
for (i, y) in frames_in.iter().enumerate().take(5) {
let _ = enc.encode(y).unwrap_or_else(|_| panic!("frame {i}"));
}
let t = Instant::now();
for (i, y) in frames_in.iter().cycle().take(frames).enumerate() {
let _ = enc.encode(y).unwrap_or_else(|_| panic!("frame {i}"));
}
t.elapsed().as_millis() as f64 / frames as f64
}
fn main() {
println!("1080p 噪声帧编码基准(含 BGRA→YUV 转换)");
let t = Instant::now();
let _ = YUVBuffer::from_bgra8_source(BgraSliceU8::new(
&vec![7u8; 1920 * 1080 * 4],
(1920, 1080),
));
println!("BGRA→YUV 转换: {}ms/帧", t.elapsed().as_millis());
let s = bench(1, 20);
println!("单线程: {s:.1}ms/帧 → {}fps", (1000.0 / s) as u32);
let m = bench(4, 20);
println!("4 线程: {m:.1}ms/帧 → {}fps", (1000.0 / m) as u32);
}